赞
踩
串口(USART)是一种通用的同步/异步收发器,可以实现串行通信的功能。串行通信是指数据按位顺序依次传输,相比并行通信,占用的引脚资源少,但速度较慢。串口通信需要有一定的通信协议,即双方约定的数据传输的规则和约定。通常,串口通信的协议包括以下几个要素:
- 波特率:表示每秒钟传输的码元(信号单元)的个数,单位是波特(Baud)。波特率越高,数据传输的速率越快,但也越容易出错。波特率是由串口的波特率寄存器(USART_BRR)控制的,通常可以通过计算或查表的方式得到波特率寄存器的值。
- 数据位:表示每个码元包含的二进制位的个数,一般有5、6、7、8、9等几种选择。数据位越多,可以传输的信息量越大,但也占用的时间越长。
- 奇偶校验位:表示是否对数据位进行奇偶校验,用于检测数据传输是否正确。一般有无校验、奇校验、偶校验三种选择。无校验表示不进行校验,奇校验表示数据位的1的个数为奇数时,校验位为0,否则为1,偶校验则相反。
- 停止位:表示数据传输结束的标志位,可以是1位、1.5位或2位。停止位的位数越多,数据传输的稳定性越高,但速度也越慢。
串口通信的数据类型主要有两种:字符型和数值型。字符型数据是指按照ASCII码或其他编码方式传输的字符,如字母、数字、符号等。数值型数据是指按照二进制或十六进制等方式传输的数值,如整数、浮点数等。不同的数据类型在串口通信中有不同的处理方式,下面分别介绍。
字符型数据的收发
字符型数据的收发比较简单,只需要调用库函数即可。STM32提供了以下几个库函数:
- void USART_SendData(USART_TypeDef* USARTx, uint16_t Data):用于发送单个字符,第一个参数是串口号,第二个参数是要发送的字符。该函数会将字符写入发送数据寄存器(USART_DR),然后等待发送移位寄存器为空,再将数据逐位发送出去。
- uint16_t USART_ReceiveData(USART_TypeDef* USARTx):用于接收单个字符,参数是串口号。该函数会从接收数据寄存器(USART_DR)读取字符,然后返回给调用者。
- int fputc(int ch, FILE *f):用于重定义标准输出函数,使得可以使用printf等函数向串口发送字符。该函数需要调用USART_SendData函数来实现。
- int fgetc(FILE *f):用于重定义标准输入函数,使得可以使用scanf等函数从串口接收字
- 符。该函数需要调用USART_ReceiveData函数来实现。
以下是一个使用字符型数据的收发的示例代码,实现了STM32通过串口1和上位机(PC)对话的功能,即将接收到的字符原样返回给上位机。
-
-
- /* 发送单个字符 */
- void Usart_SendByte(USART_TypeDef* pUSARTx, uint8_t data)
- {
- USART_SendData(pUSARTx, data); // 调用库函数发送数据
- while(USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET); // 等待发送完成
- }
- 发送字符串 **
- void Usart_SendString( USART_TypeDef * pUSARTx, char *str)
- {
- unsigned int k=0;
- do
- {
- Usart_SendByte( pUSARTx, *(str + k) );
- k++;
- } while(*(str + k)!='\0');
-
- /* 等待发送完成 */
- while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET)
- {}
- }
-
-
- /* 串口接收中断服务函数 */
- void USART1_IRQHandler(void)
- {
- uint8_t ucTemp;
- if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) // 判断是否有接收中断
- {
- ucTemp = USART_ReceiveData(USART1); // 调用库函数接收数据
- USART_SendData(USART1, ucTemp); // 调用库函数发送数据
- }
-
数值型数据的收发比较复杂,因为需要考虑数据的格式和大小端问题。数据的格式是指数据是按照二进制、十进制、十六进制等方式表示的,不同的格式在串口通信中有不同的表示方法。数据的大小端是指数据在内存中的存储顺序,大端模式是指高位字节存放在低地址,低位字节存放在高地址,小端模式则相反。STM32是小端模式的处理器,而串口通信一般是大端模式的,所以在数据收发时需要进行大小端的转换。
数值型数据的收发一般有以下几种方法:
-
-
-
- /* 发送浮点数 */
- void Usart_SendFloat(USART_TypeDef* pUSARTx, float data)
- {
- uint8_t i;
- union
- {
- float f;
- uint8_t c[4];
- }u; // 定义一个联合体,用于浮点数和字节数组的转换
- u.f = data; // 将浮点数赋值给联合体
- for(i = 0; i < 4; i++)
- {
- Usart_SendByte(pUSARTx, u.c[3-i]); // 逆序发送字节,实现大小端的转换
- }
- }
-
- /* 接收浮点数 */
- float Usart_ReceiveFloat(USART_TypeDef* pUSARTx)
- {
- uint8_t i;
- union
- {
- float f;
- uint8_t c[4];
- }u; // 定义一个联合体,用于浮点数和字节数组的转换
- for(i = 0; i < 4; i++)
- {
- u.c[3-i] = USART_ReceiveData(pUSARTx); // 逆序接收字节,实现大小端的转换
- while(USART_GetFlagStatus(pUSARTx, USART_FLAG_RXNE) == RESET); // 等待接收完成
- }
- return u.f; // 返回浮点数
- }
- 串口发送数字
- * 参 数:Number 要发送的数字,范围:0~4294967295
- * 参 数:Length 要发送数字的长度,范围:0~10
- * 返 回 值:无
- */
- void Serial_SendNumber(uint32_t Number, uint8_t Length)
- {
- uint8_t i;
- for (i = 0; i < Length; i ++) //根据数字长度遍历数字的每一位
- {
- Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0'); //依次调用Serial_SendByte发送每位数字
- }
- }
其实说到底无非就是发送和接收这两个函数,那种类型的发送按照自己的需求进行封装,这样当然最好,当然上面的程序使用或者用来参考也是可以的。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。