shuihehe 发表于 2019-4-30 16:58:13

用寄存器 解决

edmundlee 发表于 2019-5-1 13:13:06

兄弟,你会遇到这问题是因为你的编程思维方式还是停留在面向过程, 去搜一下状态机编程方法, 会对你有很大的帮助

streamlee 发表于 2019-6-14 11:30:31

本人也是从传统的51单片机走过来的,习惯用寄存器直接操作串口,std标准库也比较顺手,最近搞cube接触了这个hal库,不得不说这个库很繁琐,封装太多,自然没有直接操作寄存器和std标准库效率高,但是还是探索了一番:在cube的FreeRTOS环境下,利用HAL操作串口, 发送使用非中断,接收使用中断。

streamlee 发表于 2019-6-14 11:33:13

本帖最后由 streamlee 于 2019-6-14 12:13 编辑

1、初始化直接使用cube生产的代码,不做修改/* USART1 init function */
static void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_8;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
    _Error_Handler(__FILE__, __LINE__);
}
}

2、发送重写printf,加互斥量
static char string;
void my_printf(char *fmt,...)
{
va_list ap;
osMutexWait(debug_mutex_id,osWaitForever);
va_start(ap,fmt);
vsprintf(string,fmt,ap);
HAL_UART_Transmit(&huart1, (uint8_t*)string, strlen(string), 100);
//HAL_UART_Transmit_IT(&huart1, (uint8_t*)string, strlen(string));
va_end(ap);
osMutexRelease(debug_mutex_id);
}

3、接收单独一个task处理,使用中断方式,配合FreeRTOS的等待信号量超时操作,处理不定长接收。超时时间定为10ms。
void taskUart(void const * argument)
{
uint8_t *buf1 = pvPortMalloc(256);
uint8_t *buf2 = pvPortMalloc(256);
uint8_t *uartTXbuf= buf1;
uint8_t *recvData = uartTXbuf;
uint16_t lenth;
(char*)argument;
osSemaphoreWait(uartRx_sem_id,0);
if(!buf1 || !buf2)
{
    my_printf("%s[%d]:pvPortMalloc buf1 or buf2 fail!\r\n",__FUNCTION__,__LINE__);
    while(1){};
}
my_printf("%s:ready\r\n",__FUNCTION__);
HAL_UART_Receive_IT(&huart1,uartTXbuf,256);
while(1)
{
   osSemaphoreWait(uartRx_sem_id,10);
   recvData = uartTXbuf;
   lenth = 256 - huart1.RxXferCount;
   HAL_UART_AbortReceive_IT(&huart1);
   if(uartTXbuf == buf1)//乒乓操作
       uartTXbuf = buf2;
   else
       uartTXbuf = buf1;
   if(HAL_UART_Receive_IT(&huart1,uartTXbuf,256)!=HAL_OK)
   {
      my_printf("%s:HAL_UART_Receive_IT not ok!\r\n",__FUNCTION__);
   }
   if(lenth>0)
   {
      uartDataPro(recvData,lenth);
   }
}
}

4、接收完成中断自然是发送信号量
/* USER CODE BEGIN 0 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
osSemaphoreRelease(uartRx_sem_id);
}
/* USER CODE END 0 */

5、串口实际效果如下图所示:(uartDataPro(recvData,lenth);直接把接收的数据打印了出来并添加回车换行)
由于接收超时时间是10ms,串口工具发送时间是随机,所以可以看到有些数据被分成了2段接收,但是并没有数据丢失,得益于我们采用的乒乓操作和串口任务的高优先级,接收超时后,立刻切换buf后重新开启接收中断。

edmundlee 发表于 2019-6-14 13:07:41

库, 我只来配置外设。

zhjb1 发表于 2019-10-17 10:47:36

谢谢各位同仁!因为搬家一直没有时间玩这些,稳定后会回来的!

caoenq 发表于 2020-1-5 11:27:01

ringsp 发表于 2018-9-8 07:10
一大帮干单片机的,看到st的驱动库惊为高科技。用过环形队列做串口收发吗?真正理解钩子函数吗?用过链表 ...

建议赶紧去医院检查一下脑子。
页: 1 2 3 [4]
查看完整版本: 再次质疑 HAL_UART_Receive_IT函数