stm32之USART

来源:互联网 发布:野兽骑行 知乎 编辑:程序博客网 时间:2024/05/29 09:51
  • 重温串口的通讯协议,我们知道要配置串口通讯,至少要设置以下几个参数:字长(一次传送的数据长度)、波特率(每秒传输的数据位数)、奇偶校验位、还有停止位。对ST库函数的使用已经上手的读者应该能猜到,在初始化串口的时候,必然有一个串口初始化结构体,这个结构体的几个成员肯定就是有来存储这些控制参数的。
  • 串口工作过程分析
    波特率控制 
    波特率,即每秒传输的二进制位数,用 b/s (bps)表示,通过对时钟的控制可以改变波特率。在配置波特率时,我们向波特比率寄存器USART_BRR写入参数,修改了串口时钟的分频值USARTDIV。USART_BRR寄存器包括两部分,分别是DIV_Mantissa(USARTDIV的整数部分)和DIVFraction(USARTDIV的小数)部分,最终,计算公式为USARTDIV=DIV_Mantissa+(DIVFraction/16)。 

    收发控制
    围绕着发送器和接收器控制部分,有好多个寄存器:CR1、CR2、CR3、SR,即USART的三个控制寄存器(Control Register)及一个状态寄存器(Status Register)。通过向寄存器写入各种控制参数,来控制发送和接收,如奇偶校验位,停止位等,还包括对USART中断的控制;串口的状态在任何时候都可以从状态寄存器中查询得到。具体的控制和状态检查,我们都是使用库函数来实现的,在此就不具体分析这些寄存器位了。




    数据存储与转移
    收发控制器根据我们的寄存器配置,对数据存储转移部分的移位寄存器进行控制。当我们需要发送数据时,内核把数据从内存(变量)写入到发送数据寄存器TDR后,发送控制器将适时地自动把数据从TDR加载到发送移位寄存器,然后通过串口线Tx,把数据一位一位地发送出去,在数据从TDR转移到移位寄存器时,会产生发送寄存器TDR已空事件TXE,当数据从移位寄存器全部发送出去时,会产生数据发送完成事件TC,这些事件可以在状态寄存器中查询到。 而接收数据则是一个逆过程,数据从串口线Rx一位一位地输入到接收移位寄存器,然后自动地转移到接收数据寄存器RDR,最后用内核指令读取到内存(变量)中。


     
  • 实验分析
    实验要求:串口收发信息。
    硬件图

    程序
    #include "stm32f10x.h"#include "stdio.h"#include "stdarg.h"void RCC_Configuration(void);void GPIO_Configuration(void);void USART_Configuration(void);int fputc(int ch, FILE *f);void USART_OUT(USART_TypeDef* USARTx, uint8_t *Data,...);char *itoa(int value, char *string, int radix);int main(){u16 i = 0;RCC_Configuration();GPIO_Configuration();USART_Configuration();printf("\r\nWelcome!\r\n");printf("\r\n你好,严世富\r\n");USART_OUT(USART1,"\r 好好学习,天天向上!\n");while(1){if(USART_GetFlagStatus(USART1 , USART_FLAG_RXNE) == SET){USART_SendData(USART1,USART_ReceiveData(USART1));for(i = 0; i < 500; i++);}}}void USART_OUT(USART_TypeDef* USARTx, uint8_t *Data,...){ const char *s;    int d;    char buf[16];    va_list ap;    va_start(ap, Data);while(*Data!=0){                          //判断是否到达字符串结束符if(*Data==0x5c){  //'\'switch (*++Data){case 'r':          //回车符USART_SendData(USARTx, 0x0d);   Data++;break;case 'n':          //换行符USART_SendData(USARTx, 0x0a);Data++;break;default:Data++;    break;} }else if(*Data=='%'){  //switch (*++Data){case 's':  //字符串                s = va_arg(ap, const char *);                for ( ; *s; s++) {                    USART_SendData(USARTx,*s);while(USART_GetFlagStatus(USARTx, USART_FLAG_TC)==RESET);                }Data++;                break;            case 'd':  //十进制                d = va_arg(ap, int);                itoa(d, buf, 10);                for (s = buf; *s; s++) {                    USART_SendData(USARTx,*s);while(USART_GetFlagStatus(USARTx, USART_FLAG_TC)==RESET);                }Data++;                break;default:Data++;    break;} }else USART_SendData(USARTx, *Data++);while(USART_GetFlagStatus(USARTx, USART_FLAG_TC)==RESET);}}char *itoa(int value, char *string, int radix){    int     i, d;    int     flag = 0;    char    *ptr = string;    /* This implementation only works for decimal numbers. */    if (radix != 10)    {        *ptr = 0;        return string;    }    if (!value)    {        *ptr++ = 0x30;        *ptr = 0;        return string;    }    /* if this is a negative value insert the minus sign. */    if (value < 0)    {        *ptr++ = '-';        /* Make the value positive. */        value *= -1;    }    for (i = 10000; i > 0; i /= 10)    {        d = value / i;        if (d || flag)        {            *ptr++ = (char)(d + 0x30);            value -= (d * i);            flag = 1;        }    }    /* Null terminate the string. */    *ptr = 0;    return string;} /* NCL_Itoa */void RCC_Configuration(void){RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);}void GPIO_Configuration(void){GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, &GPIO_InitStructure);}void USART_Configuration(void){USART_InitTypeDef USART_InitStructure;USART_InitStructure.USART_BaudRate = 115200;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_Parity = USART_Parity_No;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;USART_Init(USART1, &USART_InitStructure);USART_Cmd(USART1 , ENABLE);}int fputc(int ch,FILE *f){USART_SendData(USART1,(u8) ch);while(USART_GetFlagStatus(USART1,USART_FLAG_TC) == RESET);return ch;}



0 0