- 重温串口的通讯协议,我们知道要配置串口通讯,至少要设置以下几个参数:字长(一次传送的数据长度)、波特率(每秒传输的数据位数)、奇偶校验位、还有停止位。对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; }
stm32之USART
最新推荐文章于 2024-03-31 23:09:08 发布