SM32 USART与USB接收不定数据方法,标准库、HAL库都适用

 

       很多时候,我们使用串口或USB接收数据时,往往不知道PC端会发多长的数据下来,

为了解决这个不定数据接收问题,在此各提供一个解决思路。

串口数据不定接收:

  由于STM32单片机带IDLE中断,所以利用这个中断,可以接收不定长字节的数据,

由于STM32属于ARM单片机,所以这篇文章的方法也适合其他的ARM单片机。

       IDLE就是串口收到一帧数据后,发生的中断。什么是一帧数据呢?比如说给单片机一

次发来1个字节,或者一次发来8个字节,这些一次发来的数据,就称为一帧数据,也可以

叫做一包数据。

        还有一个RXNE中断,当接收到1个字节,就会产生RXNE中断,当接收到一帧数据,就

会产生IDLE中断。比如给单片机一次性发送8个字节,就会产生8次RXNE中断,1次IDLE中断。

       这里只写RXNE中断例子,IDLE中断的类似,只是寄存器地址不同,各位可以查手册编写。

eg:

  在中断服务函数里添加一下代码,函数外部定义 buff[ ] 和 i=0 ; 我这里使用的是串口1:

  if(UASART_GetITStatus(UASART1, UASART_IT_RXNE != RESET)) //接收一个字节判断

  {

    buff [i++] = UASART1->DR;       //把接收到的字节保存到数组后,数组下标自加1

  }

  就这么几句代码就可以实现了,buff[ ],就是接收到的数据,i-1 就是数据长度了

=======================================================================

USB不定数据接收:

        usb不定数据接收,利用了定时器作为校验来接收,这个方法通用性强,适用于uasart

也适用于usb,还使用于hal库。不过这个方法有一个局限性,就是PC端发送数据过来的时间

间隔不可以太短,否则会出现误判情况。

       定时器方法的原理是:先定时一个时间间隔合适的时间,一般几毫秒就可以了,然后在

接收服务函数里把接收到的数据存到buff[ ],i++,接着定时器计数值清0,打开定时器,如果

数据没接受完,每次接收都清空了定时器计数器,使得定时器无法进入定时器中断。如果数据

接收完成了,则过不会清空定时器计数器,进入定时器中断,此时则判断数据已经接收完成,

可以在定时器中断中取出数据和数据长度。

       eg:

       这里我是用HAL库作为例子,在usbd_cdc_if.c文件中找到USB接收中断服务函数,在里面

修改代码即可。

  

 

  

  

  

 

        因为usb发送,每发送最大包是64个字节,而且usb接收可以自己算出接收长度,不过超

过64字节就会出错,所以我这里进行了一个最大包处理。

 

转载于:https://www.cnblogs.com/xingboy/p/9415653.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 好的,以下是一个基于STM32F4 HALUSART接收数据,通过USB发送,采用USB双缓存技术的示例。 首先,需要初始化USARTUSB。 ```c /* USART initialization */ UART_HandleTypeDef huart; huart.Instance = USART1; huart.Init.BaudRate = 115200; huart.Init.WordLength = UART_WORDLENGTH_8B; huart.Init.StopBits = UART_STOPBITS_1; huart.Init.Parity = UART_PARITY_NONE; huart.Init.Mode = UART_MODE_RX; huart.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart) != HAL_OK) { Error_Handler(); } /* USB initialization */ USBD_HandleTypeDef hUsbDeviceFS; hUsbDeviceFS.pUserData = &huart; USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS); USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC); USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS); USBD_Start(&hUsbDeviceFS); ``` 然后,需要使用HAL提供的回调函数来处理USART接收数据USB发送数据。 ```c void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { /* Write received data to USB */ uint8_t buf[1]; buf[0] = huart->Instance->DR & 0xFF; CDC_Transmit_FS(buf, 1); /* Restart USART receive */ HAL_UART_Receive_IT(huart, buf, 1); } int8_t CDC_Receive_FS(uint8_t *buf, uint32_t len) { /* Write received USB data to USART */ HAL_UART_Transmit(&huart, buf, len, HAL_MAX_DELAY); return (USBD_OK); } ``` 最后,在main函数中启动USART接收USB接收。 ```c int main(void) { /* Start USART receive */ uint8_t buf[1]; HAL_UART_Receive_IT(&huart, buf, 1); while (1) {} } ``` 这个示例使用了USB双缓存技术,因为USB的传输速度比USART慢得多,所以需要使用双缓存来避免数据丢失。在上面的回调函数中,每当USART接收到一个字节时,就会将其写入USB的发送缓存中。然后,在USB的发送完成回调函数中,会从另一个缓存中读取数据并发送到主机。 需要注意的是,这个示例中的USART模式为UART_MODE_RX,即只接收数据不发送数据。如果需要发送数据,需要将模式改为UART_MODE_TX或UART_MODE_TX_RX。 ### 回答2: STM32F4 HAL提供了USART接收数据的功能。 首先,需要初始化USARTUSB模块。调用HAL_UART_Init()函数初始化USART,设置波特率、数据位、停止位等参数。然后,调用HAL_UART_Receive_DMA()函数启动USART的DMA接收模式,设置接收数据缓存和缓存长度。 接下来,配置USB模块。初始化USB模块,调用HAL_PCD_Init()函数。然后,设置USB传输模式为双缓存模式,调用HAL_PCDEx_SetRxFiFo()函数设置接收FIFO的大小和地址。 当USART接收数据后,DMA会自动将数据存储到指定的接收缓存中。收到数据后,可以通过USB发送数据。调用HAL_PCDEx_PMAConfig()函数设置USB发送缓冲区的地址和大小。通过调用HAL_PCD_EP_Tx()函数发送数据。 在主循环中,可以通过调用HAL_UART_Receive_DMA()函数来接收更多的数据。同时,也可以通过调用HAL_PCD_EP_Tx()函数来发送更多的数据。 需要注意的是,在使用USB双缓存技术时,需要注意数据的同步。可以通过使用信号量或者互斥锁来保证数据的一致性。 以上就是使用STM32F4 HAL实现USART接收数据,并通过USB发送数据的简单示例。通过使用USB双缓存技术,可以更有效地处理数据,提高系统的性能和稳定性。 ### 回答3: 在STM32F4中使用HAL实现USART接收数据并通过USB发送,可以采用USB双缓存技术进行数据传输。下面是一个示例: 1. 首先,需要在CubeMX中配置USARTUSB模块。选择需要的GPIO引脚作为USART接收引脚和USB的DP、DN引脚。 2. 在代码中包含必要的文件: ```c #include "main.h" #include "usart.h" #include "usb_device.h" ``` 3. 配置HALUSARTUSB: ```c MX_USART1_UART_Init(); MX_USB_DEVICE_Init(); ``` 4. 在主函数中初始化变量和缓存: ```c uint8_t usartRxBuffer[256]; uint8_t usbTxBuffer[256]; ``` 5. 在USART接收中断回调函数中,将接收到的数据存入缓存: ```c void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { static uint8_t index = 0; usartRxBuffer[index] = USART1->DR; index++; // 接收到一组数据后,将数据发送到USB if (接收到的数据满足条件) { CDC_Transmit_FS(usartRxBuffer, index); index = 0; } HAL_UART_Receive_IT(&huart1, &(usartRxBuffer[index]), 1); } ``` 6. 在USB发送函数中,将数据USART接收缓存复制到USB发送缓存: ```c uint8_t CDC_Transmit_FS(uint8_t *buf, uint16_t len) { // 复制数据USB发送缓存 memcpy(usbTxBuffer, buf, len); return (USBD_CDC_SetTxBuffer(&hUsbDeviceFS, usbTxBuffer, len) == USBD_OK); } ``` 7. 最后,在main函数中启动USARTUSB: ```c HAL_UART_Receive_IT(&huart1, usartRxBuffer, 1); MX_USB_DEVICE_Init(); ``` 通过以上步骤,我们成功实现了使用STM32F4 HAL进行USART接收数据,并通过USB发送,采用了USB双缓存技术来提高数据传输效率。当接收到完整的数据后,将数据USART接收缓存复制到USB发送缓存,并通过USB发送出去。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值