STM32串口(USART)详解2 收发数据类型

1.重复概念

串口(USART)是一种通用的同步/异步收发器,可以实现串行通信的功能。串行通信是指数据按位顺序依次传输,相比并行通信,占用的引脚资源少,但速度较慢。串口通信需要有一定的通信协议,即双方约定的数据传输的规则和约定。通常,串口通信的协议包括以下几个要素:

  • 波特率:表示每秒钟传输的码元(信号单元)的个数,单位是波特(Baud)。波特率越高,数据传输的速率越快,但也越容易出错。波特率是由串口的波特率寄存器(USART_BRR)控制的,通常可以通过计算或查表的方式得到波特率寄存器的值。
  • 数据位:表示每个码元包含的二进制位的个数,一般有5、6、7、8、9等几种选择。数据位越多,可以传输的信息量越大,但也占用的时间越长。
  • 奇偶校验位:表示是否对数据位进行奇偶校验,用于检测数据传输是否正确。一般有无校验、奇校验、偶校验三种选择。无校验表示不进行校验,奇校验表示数据位的1的个数为奇数时,校验位为0,否则为1,偶校验则相反。
  • 停止位:表示数据传输结束的标志位,可以是1位、1.5位或2位。停止位的位数越多,数据传输的稳定性越高,但速度也越慢。

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函数来实现。 

3.字符型数据的收发的示例代码

以下是一个使用字符型数据的收发的示例代码,实现了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); // 调用库函数发送数据
    }

4.数值型数据的收发的示例代码 

数值型数据的收发比较复杂,因为需要考虑数据的格式和大小端问题。数据的格式是指数据是按照二进制、十进制、十六进制等方式表示的,不同的格式在串口通信中有不同的表示方法。数据的大小端是指数据在内存中的存储顺序,大端模式是指高位字节存放在低地址,低位字节存放在高地址,小端模式则相反。STM32是小端模式的处理器,而串口通信一般是大端模式的,所以在数据收发时需要进行大小端的转换。

数值型数据的收发一般有以下几种方法:

  • 使用sprintf和sscanf函数:这种方法可以将数值转换成字符串,然后使用字符型数据的收发函数进行传输。这种方法的优点是简单易用,缺点是占用内存和时间较多,而且不能传输浮点数。
  • 使用memcpy和union结构体:这种方法可以将数值拆分成字节,然后逐个字节进行传输。这种方法的优点是占用内存和时间较少,而且可以传输浮点数。
  • 使用位运算和移位操作:这种方法可以将数值按位进行操作,然后按照一定的顺序进行传输。这种方法的优点是效率最高,而且可以灵活地控制数据的格式和大小端,缺点是编程较复杂,而且需要注意数据的溢出和符号问题。



/* 发送浮点数 */
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发送每位数字
	}
}

5.结语

其实说到底无非就是发送和接收这两个函数,那种类型的发送按照自己的需求进行封装,这样当然最好,当然上面的程序使用或者用来参考也是可以的。

  • 28
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是基于标准库STM32USART3中断收发数据代码的实现: 首先,在STM32CubeMX中配置USART3。在“Pinout & Configuration”选项卡中,将USART3的引脚分配给适当的GPIO引脚,并将USART3配置为异步模式。然后在“Configuration”选项卡中使能USART3的中断,并勾选“RXNE”和“TXE”中断。 接下来,使用以下代码初始化USART3: ``` #include "stm32f4xx.h" void USART3_Init(void) { // Enable USART3 clock RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); // Configure USART3 GPIO pins GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART3; HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); // Configure USART3 USART_InitTypeDef USART_InitStruct; USART_InitStruct.BaudRate = 115200; USART_InitStruct.WordLength = USART_WORDLENGTH_8B; USART_InitStruct.StopBits = USART_STOPBITS_1; USART_InitStruct.Parity = USART_PARITY_NONE; USART_InitStruct.Mode = USART_MODE_TX_RX; USART_InitStruct.CLKPolarity = USART_POLARITY_LOW; USART_InitStruct.CLKPhase = USART_PHASE_1EDGE; USART_InitStruct.CLKLastBit = USART_LASTBIT_DISABLE; HAL_USART_Init(&huart3, &USART_InitStruct); // Enable USART3 interrupts HAL_NVIC_SetPriority(USART3_IRQn, 0, 1); HAL_NVIC_EnableIRQ(USART3_IRQn); // Enable USART3 USART_Cmd(USART3, ENABLE); } ``` 在USART3中断处理函数中,可以使用以下代码接收数据: ``` void USART3_IRQHandler(void) { if (__HAL_USART_GET_FLAG(&huart3, USART_FLAG_RXNE) != RESET) { uint8_t data = USART_ReceiveData(USART3); // Do something with received data } } ``` 发送数据时,可以使用以下代码: ``` void USART3_Send(uint8_t data) { while (__HAL_USART_GET_FLAG(&huart3, USART_FLAG_TXE) == RESET); USART_SendData(USART3, data); } ``` 注意,在使用以上代码之前,需要创建一个名为“huart3”的全局USART_HandleTypeDef变量,并在main函数中调用USART3_Init函数初始化USART3。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值