硬汉嵌入式论坛

 找回密码
 立即注册
查看: 854|回复: 7
收起左侧

[UART] 请教一个DMA缓冲区的问题

[复制链接]

3

主题

13

回帖

22

积分

新手上路

积分
22
发表于 2022-3-4 09:35:16 | 显示全部楼层 |阅读模式
如题,我串口接收开了DMA,循环模式接收到数据放到一个(缓冲区)数组里,请教下我能不能不开DMA中断,在主程序中进行读写这个(缓冲区)数组;请教下两个地方的读写有没有冲突?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106974
QQ
发表于 2022-3-4 10:10:15 | 显示全部楼层
在串口的回调里面更好。因为DMA传输有下面这么个问题。

image.png
回复

使用道具 举报

5

主题

192

回帖

212

积分

高级会员

积分
212
发表于 2022-3-4 10:21:52 | 显示全部楼层
你是循环模式,不开中断怎么知道什么时候DMA传输完成,要是你和DMA抢夺内存使用权会出错的。
回复

使用道具 举报

3

主题

13

回帖

22

积分

新手上路

积分
22
 楼主| 发表于 2022-3-4 11:12:07 | 显示全部楼层
我程序需要不停的处理串口过来的数据,而且不能进中断;我的想法是能不能类似环形FIFO一样,DMA不停的环形压栈;我主程序中去不停地读取
回复

使用道具 举报

2

主题

269

回帖

275

积分

高级会员

积分
275
发表于 2022-3-4 11:39:52 | 显示全部楼层
arm_uclinux 发表于 2022-3-4 11:12
我程序需要不停的处理串口过来的数据,而且不能进中断;我的想法是能不能类似环形FIFO一样,DMA不停的环形 ...

可以,你得保证,FIFO不会发生溢出。自己维护读指针,写入指针从DMA读出来就行有相关函数。
推荐读下KFIFO相关文章
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106974
QQ
发表于 2022-3-4 12:08:08 | 显示全部楼层
arm_uclinux 发表于 2022-3-4 11:12
我程序需要不停的处理串口过来的数据,而且不能进中断;我的想法是能不能类似环形FIFO一样,DMA不停的环形 ...

DMA双缓冲。此时可以把DMA中断开启了,注意传输完成标志状态即可。
回复

使用道具 举报

3

主题

13

回帖

22

积分

新手上路

积分
22
 楼主| 发表于 2022-3-4 16:06:00 | 显示全部楼层
eric2013 发表于 2022-3-4 12:08
DMA双缓冲。此时可以把DMA中断开启了,注意传输完成标志状态即可。

好的,多谢!
回复

使用道具 举报

19

主题

62

回帖

119

积分

初级会员

积分
119
发表于 2022-3-9 22:47:06 | 显示全部楼层
可以不是用中断,如果实时性要求不高,完全不知道什么时候传输完成,只需要在cpu空闲的时候去dma的buf取出数据来处理就好了,下面是在项目中实际使用的无中断dma版本串口驱动uart.h
  1. /** ****************************************************************************
  2. * @file         uart.h
  3. * @author         mojinpan
  4. * @copyright (c) 2018-20xx JL Tech. Co., Ltd.
  5. * @brief         串口驱动,DMA环形buf方式
  6. * @version         V1.4
  7. * @date         2020-11-22
  8. *
  9. * @par 功能说明
  10. * @details
  11. * 1.提供STM32H7系列CPU的UART驱动支持
  12. * 2.提供将printf重定向到指定UART的支持
  13. *
  14. * @par 移植说明
  15. * @details
  16. * 1.定义硬件管脚宏定义
  17. * 2.定义UART对象
  18. * 4.调用UART_Init()进行初始化
  19. * 5.调用Uart_Link2Console()重定向printf和scanf到指定串口(非必须)
  20. *                
  21. * @par 调用说明
  22. * @details
  23. * 1.调用UART_Send()发数据
  24. * 2.必须通过UART_GetDataLen()查询是否有接收数据并调用UART_Recv()从buf中取出数据
  25. * 3.接收数据的轮询间隔由UART_BUF_LEN的大小及波特率决定,未能及时取走数据会存在被覆盖的风险
  26. *******************************************************************************/
  27. #ifndef __UART_H__
  28. #define __UART_H__


  29. #if defined(__cplusplus)
  30. extern "C" {
  31. #endif
  32. /*******************************************************************************
  33.                                                                         Header Files 头文件
  34. *******************************************************************************/

  35. /*******************************************************************************
  36.                                                                         Macro Definition 宏定义
  37. *******************************************************************************/
  38. // #define STDIO_IS_UART                   //开启uart重定向到stdout和stdin
  39. #define UART_BUF_LEN                          256                        //环形buf长度
  40. #define UART_TIMEOUT_MAX                10000                //超时等待,n个时钟周期
  41. //debug信息输出方式
  42. #define UART_DEBUG(...)                  printf(__VA_ARGS__);printf("\r\n")               
  43. //uart通道定义
  44. #define COM0                               LPUART1
  45. #define COM1                               USART1
  46. #define COM2                               USART2
  47. #define COM3                               USART3
  48. #define COM4                               UART4
  49. #define COM5                               UART5
  50. #define COM6                               USART6
  51. #define COM7                               UART7
  52. #define COM8                               UART8

  53. //uart状态
  54. #define UART_OK                                        0
  55. #define UART_SET_ERR                        1
  56. #define UART_DATA_ERR                        2
  57. #define UART_WIRTE_ERR                        3

  58. /*******************************************************************************
  59.                                                                         Data Type 数据类型
  60. *******************************************************************************/
  61. ///* @brief uart对象
  62. typedef struct
  63. {
  64.         USART_TypeDef* idx;                                //uart基地址
  65.         uint32_t bps;                                        //波特率
  66.         uint32_t state;                                        //uart当前状态,具体定义见宏定义
  67.         UART_HandleTypeDef huart;                //uart配置信息
  68.         DMA_HandleTypeDef hdma_rx;                //rx的dma信息
  69.         struct                                                        //rx的环形buf                                                                       
  70.         {
  71.                 uint32_t        iIdx;
  72.                 uint32_t        oIdx;
  73.         uint8_t*        data;       
  74.         size_t    len;
  75.         }rbuf;
  76. } UART_Device;

  77. /*******************************************************************************
  78.                                                                         Function declaration 函数声明
  79. *******************************************************************************/
  80. uint8_t Uart_Init(UART_Device* dev,USART_TypeDef* uart,uint32_t bps,uint8_t* buf,size_t len);
  81. uint8_t UART_Send(UART_Device* dev,uint8_t *buf, size_t len);
  82. uint32_t UART_Recv(UART_Device* dev,uint8_t *buf, size_t len);
  83. uint32_t UART_GetDataLen(UART_Device* dev);
  84. void Uart_ClearBuf(UART_Device *dev);

  85. void Uart_Link2Console(UART_Device *uart);
  86. signed char Uart_ConsoleRecvByte(char* recvData);
  87. void Uart_ConsoleSendByte(const char data);
  88. void Uart_ConsoleSend(uint8_t *buf, size_t len);
  89. uint8_t Uart_DeInit(UART_Device* dev);

  90. #if defined(__cplusplus)
  91. }
  92. #endif

  93. #endif

  94. /*********************************END OF FILE**********************************/
复制代码


uart.c
  1. /** ****************************************************************************
  2. * @file         uart.c
  3. * @author         mojinpan
  4. * @copyright (c) 2018-20xx JL Tech. Co., Ltd.
  5. * @brief         串口驱动,DMA环形buf方式
  6. * @version         V1.4
  7. * @date         2020-11-22
  8. *
  9. * @version         V1.0
  10. * @date         2020-04-22
  11. * @details
  12. * 1.将STM32F7的串口驱动移植到STM32H7上
  13. * 2.增加UART_NEW()的宏定义用于将对象结构件UART_Device强制指定到SRAM中,否则DMA无法访问buf
  14. * 3.UART_Recv()函数增加对Dcache的清除操作,以便正确读取到SRAM中buf的数据
  15. *
  16. * @version         V1.1
  17. * @date         2020-07-07
  18. * @details
  19. * 1.完善驱动,将所有串口都引出
  20. *
  21. * @version         V1.2
  22. * @date         2020-07-28
  23. * @details
  24. * 1.扩大UART_Recv()中删除Dcache的范围,解决buf最后4个字节,在连续数据输入时可能无法更新的bug
  25. * 2.DmaInit()中按照勘误要求在UART使用DMA时需对SxCR的bit20进行置位,以解决数据可能被冻结的bug
  26. *
  27. * @version         V1.3
  28. * @date         2020-08-31
  29. * @details
  30. * 1.RX和TX改为初始化成上拉模式,解决TTL模式下外部没有上拉电阻的时候出现乱码的问题
  31. *
  32. * @version         V1.4
  33. * @date         2020-11-22
  34. * @details
  35. * 1.增加STDIO_IS_UART的宏定义来控制是否做stdout和stdin的重定向
  36. *
  37. * @version         V1.4
  38. * @date         2021-04-12
  39. * @details
  40. * 1.增加AC6编译器的支持
  41. * 2.支持独立配置buf大小
  42. *******************************************************************************/
  43. #include <stdio.h>
  44. #include "bsp.h"
  45. #include "uart.h"


  46. /*******************************************************************************
  47.                                                                         Macro Definition 宏定义
  48. *******************************************************************************/

  49. /*******************************************************************************
  50.                                                                 Global Variables 全局变量
  51. *******************************************************************************/
  52. UART_Device* Puart;
  53. /** ****************************************************************************
  54. * @brief   初始化prtinf的底层函数
  55. *******************************************************************************/
  56. void Uart_Link2Console(UART_Device *uart)
  57. {
  58.         Puart = uart;
  59. }
  60. #ifdef  STDIO_IS_UART

  61. #if !defined(__MICROLIB)
  62. //#pragma import(__use_no_semihosting)
  63. __asm (".global __use_no_semihosting\n\t");
  64. void _sys_exit(int x) //避免使用半主机模式
  65. {
  66.   x = x;
  67. }
  68. //__use_no_semihosting was requested, but _ttywrch was
  69. void _ttywrch(int ch)
  70. {
  71.     ch = ch;
  72. }
  73. struct __FILE
  74. {
  75.   int handle;
  76. };
  77. FILE __stdout;

  78. #endif

  79. #if defined ( __GNUC__ ) && !defined (__clang__)
  80. #define PutChar()  __io_putchar(int ch)
  81. #else
  82. #define PutChar()  fputc(int ch, FILE *f)

  83. #endif // !defined(__MICROLIB)

  84. /** ****************************************************************************
  85. * @brief   发送一个字符
  86. *******************************************************************************/
  87. static int SendChar(int ch)
  88. {
  89.         UART_Send(Puart,(uint8_t*)&ch,1);
  90.     return ch;
  91. }
  92. /** ****************************************************************************
  93. * @brief   接收一个字符
  94. *******************************************************************************/
  95. static int GetKey(void)
  96. {
  97.     uint8_t recvData;
  98.         uint8_t i = 0;
  99.         while(i == 0)
  100.         {
  101.                 i = UART_GetDataLen(Puart);
  102.         }
  103.     UART_Recv(Puart,&recvData,1);
  104.     return recvData;       
  105. }

  106. /** ****************************************************************************
  107. * @brief   重定向_ttywrch函数,避免报错
  108. *******************************************************************************/
  109. void _ttywrch(int ch)
  110. {
  111.     SendChar(ch);
  112. }
  113. /** ****************************************************************************
  114. * @brief   重定向_ferror函数,避免报错
  115. *******************************************************************************/
  116. int _ferror(FILE *f) {

  117.   return EOF;
  118. }

  119. /** ****************************************************************************
  120. * @brief   定义_sys_exit()以避免使用半主机模式
  121. *******************************************************************************/
  122. void _sys_exit(int x)
  123. {
  124.         x = x;
  125. }

  126. /** ****************************************************************************
  127. * @brief   重定向fputc函数,以实现支持printf函数,而不需要选择use MicroLIB
  128. *******************************************************************************/
  129. int PutChar()
  130. {
  131.   /* 实现串口发送一个字节数据的函数 */
  132.         UART_Send(Puart,(uint8_t*)&ch,1);
  133.   return ch;
  134. }

  135. /** ****************************************************************************
  136. * @brief   重定向fgetc函数,以支持scanf、getchar等函数,而不需要选择use MicroLIB
  137. *******************************************************************************/
  138. int fgetc(FILE *f)
  139. {               
  140.         return (GetKey());
  141. }
  142. #endif
  143. /** ****************************************************************************
  144. * @brief  Console接收一个字符,非阻塞式
  145. * @return 0:接收成功,-1:接收失败
  146. *******************************************************************************/
  147. signed char Uart_ConsoleRecvByte(char* recvData)
  148. {
  149.     if( UART_GetDataLen(Puart))
  150.         {
  151.                 UART_Recv(Puart,(uint8_t*)recvData,1);
  152.                 return 0;
  153.         }
  154.    return -1;     
  155. }

  156. /** ****************************************************************************
  157. * @brief    Console显示一个字符
  158. * @param         data:需发送的字符
  159. *******************************************************************************/
  160. void Uart_ConsoleSendByte(const char data)
  161. {
  162.         putchar(data);
  163. }
  164. /** ****************************************************************************
  165. * @brief  串口发送函数
  166. * @param        uart: uart对象
  167. * @param        Buf:数据存放指针
  168. * @param        len:发送长度
  169. *******************************************************************************/
  170. uint8_t UART_Send(UART_Device* dev,uint8_t *buf, size_t len)
  171. {
  172.     //合法性检查
  173.     if(buf == NULL)return UART_DATA_ERR;
  174.     if(len == NULL)return UART_DATA_ERR;
  175.         if(HAL_UART_Transmit(&(dev->huart),buf,len,UART_TIMEOUT_MAX) != HAL_OK){return UART_WIRTE_ERR;}

  176.         return UART_OK;
  177. }
  178. /** ****************************************************************************
  179. * @brief    Console发送
  180. * @param        Buf:数据存放指针
  181. * @param        len:发送长度
  182. *******************************************************************************/
  183. void Uart_ConsoleSend(uint8_t *buf, size_t len)
  184. {
  185.         UART_Send(Puart,buf,len);
  186. }

  187. /** ****************************************************************************
  188. * @brief  串口接收函数,从缓冲区中取接收数据
  189. * @param        uart: uart对象
  190. * @param        Buf:数据存放指针
  191. * @param        len:接收长度
  192. *******************************************************************************/
  193. uint32_t UART_Recv(UART_Device *dev,uint8_t *buf,size_t len)
  194. {
  195.         uint32_t i = 0;

  196.     dev->rbuf.iIdx = dev->rbuf.len - __HAL_DMA_GET_COUNTER(&dev->hdma_rx);

  197.         //删除对应区域的Dcache,以便直接读取sram中内容
  198.     //cache按照32字节为块处理,+32保证整个块全部都能处理到
  199.         SCB_InvalidateDCache_by_Addr((uint32_t *)(dev->rbuf.data),dev->rbuf.len+32);
  200.    
  201.         for(i = 0;i < len;i++)
  202.         {
  203.                 if(dev->rbuf.oIdx == dev->rbuf.iIdx)
  204.                 {   // No Len data
  205.                         break;
  206.                 }
  207.                 buf[i] = dev->rbuf.data[dev->rbuf.oIdx];
  208.                 dev->rbuf.oIdx++;
  209.         dev->rbuf.oIdx = dev->rbuf.oIdx % dev->rbuf.len;
  210.         }
  211.         return i;       
  212. }
  213. /** ****************************************************************************
  214. * @brief    清空缓存
  215. * @param        uart: uart对象
  216. *******************************************************************************/
  217. void Uart_ClearBuf(UART_Device *dev)
  218. {   
  219.     dev->rbuf.iIdx = dev->rbuf.len - __HAL_DMA_GET_COUNTER(&dev->hdma_rx);
  220.     dev->rbuf.oIdx = dev->rbuf.iIdx;
  221. }
  222. /** ****************************************************************************
  223. * @brief  获取缓冲区数据长度
  224. * @param        dev: uart对象
  225. *******************************************************************************/
  226. uint32_t UART_GetDataLen(UART_Device* dev)
  227. {
  228.     dev->rbuf.iIdx = dev->rbuf.len - __HAL_DMA_GET_COUNTER(&dev->hdma_rx);
  229.     return (dev->rbuf.iIdx - dev->rbuf.oIdx + dev->rbuf.len) %  dev->rbuf.len;  
  230. }
  231. /** ****************************************************************************
  232. * @brief  初始化uart的gpio
  233. * @param dev 设备对象
  234. *******************************************************************************/
  235. static uint32_t IoInit(UART_Device* dev)
  236. {       
  237.     if(dev->idx == COM0){
  238.         #if (defined COM0_RX) &&  (defined COM0_TX)
  239.                 GPIO_Init(COM0_RX,GPIO_AF_PP_PULLUP);
  240.                 GPIO_Init(COM0_TX,GPIO_AF_PP_PULLUP);
  241.         #else
  242.         UART_DEBUG("COM0 prot not define!");
  243.         #endif
  244.         }
  245.         else if(dev->idx == COM1){
  246.         #if (defined COM1_RX) &&  (defined COM1_TX)
  247.                 GPIO_Init(COM1_RX,GPIO_AF_PP_PULLUP);
  248.                 GPIO_Init(COM1_TX,GPIO_AF_PP_PULLUP);
  249.         #else
  250.         UART_DEBUG("COM1 prot not define!");
  251.         #endif
  252.         }
  253.     else if(dev->idx == COM2){
  254.         #if (defined COM2_RX) &&  (defined COM2_TX)
  255.                 GPIO_Init(COM2_RX,GPIO_AF_PP_PULLUP);
  256.                 GPIO_Init(COM2_TX,GPIO_AF_PP_PULLUP);
  257.         #else
  258.         UART_DEBUG("COM2 prot not define!");
  259.         #endif
  260.         }
  261.     else if(dev->idx == COM3){
  262.         #if (defined COM3_RX) &&  (defined COM3_TX)
  263.                 GPIO_Init(COM3_RX,GPIO_AF_PP_PULLUP);
  264.                 GPIO_Init(COM3_TX,GPIO_AF_PP_PULLUP);
  265.         #else
  266.         UART_DEBUG("COM3 prot not define!");
  267.         #endif
  268.         }
  269.     else if(dev->idx == COM4){
  270.         #if (defined COM4_RX) &&  (defined COM4_TX)
  271.                 GPIO_Init(COM4_RX,GPIO_AF_PP_PULLUP);
  272.                 GPIO_Init(COM4_TX,GPIO_AF_PP_PULLUP);
  273.         #else
  274.         UART_DEBUG("COM4 prot not define!");
  275.         #endif
  276.         }
  277.     else if(dev->idx == COM5){
  278.         #if (defined COM5_RX) &&  (defined COM5_TX)
  279.                 GPIO_Init(COM5_RX,GPIO_AF_PP_PULLUP);
  280.                 GPIO_Init(COM5_TX,GPIO_AF_PP_PULLUP);
  281.         #else
  282.         UART_DEBUG("COM5 prot not define!");
  283.         #endif
  284.         }
  285.     else if(dev->idx == COM6){
  286.         #if (defined COM6_RX) &&  (defined COM6_TX)
  287.                 GPIO_Init(COM6_RX,GPIO_AF_PP_PULLUP);
  288.                 GPIO_Init(COM6_TX,GPIO_AF_PP_PULLUP);
  289.         #else
  290.         UART_DEBUG("COM6 prot not define!");
  291.         #endif
  292.         }
  293.     else if(dev->idx == COM7){
  294.         #if (defined COM7_RX) &&  (defined COM7_TX)
  295.                 GPIO_Init(COM7_RX,GPIO_AF_PP_PULLUP);
  296.                 GPIO_Init(COM7_TX,GPIO_AF_PP_PULLUP);
  297.         #else
  298.         UART_DEBUG("COM7 prot not define!");
  299.         #endif
  300.         }
  301.     else if(dev->idx == COM8){
  302.         #if (defined COM8_RX) &&  (defined COM8_TX)
  303.                 GPIO_Init(COM8_RX,GPIO_AF_PP_PULLUP);
  304.                 GPIO_Init(COM8_TX,GPIO_AF_PP_PULLUP);
  305.         #else
  306.         UART_DEBUG("COM8 prot not define!");
  307.         #endif
  308.         }
  309.     else
  310.     {

  311.     }

  312.         return UART_OK;       
  313. }
  314. /** ****************************************************************************
  315. * @brief 串口DMA初始化
  316. * @param dev 设备对象
  317. *******************************************************************************/
  318. static uint32_t DmaInit(UART_Device* dev)
  319. {
  320.     if(dev->idx == LPUART1){
  321.                 __HAL_RCC_BDMA_CLK_ENABLE();
  322.                 dev->hdma_rx.Instance = BDMA_Channel0;
  323.                 dev->hdma_rx.Init.Request = BDMA_REQUEST_LPUART1_RX ;
  324.         }
  325.     else if(dev->idx == USART1){
  326.                 __HAL_RCC_DMA1_CLK_ENABLE();
  327.                 dev->hdma_rx.Instance = DMA1_Stream0;
  328.                 dev->hdma_rx.Init.Request = DMA_REQUEST_USART1_RX;
  329.         }
  330.         else if(dev->idx == USART2){
  331.                 __HAL_RCC_DMA1_CLK_ENABLE();
  332.                 dev->hdma_rx.Instance = DMA1_Stream1;
  333.                 dev->hdma_rx.Init.Request = DMA_REQUEST_USART2_RX;
  334.         }
  335.     else if(dev->idx == USART3){
  336.                 __HAL_RCC_DMA1_CLK_ENABLE();
  337.                 dev->hdma_rx.Instance = DMA1_Stream2;
  338.                 dev->hdma_rx.Init.Request = DMA_REQUEST_USART3_RX;
  339.         }
  340.     else if(dev->idx == UART4){
  341.                 __HAL_RCC_DMA1_CLK_ENABLE();
  342.                 dev->hdma_rx.Instance = DMA1_Stream3;
  343.                 dev->hdma_rx.Init.Request = DMA_REQUEST_UART4_RX;

  344.         }
  345.     else if(dev->idx == UART5){
  346.                 __HAL_RCC_DMA1_CLK_ENABLE();
  347.                 dev->hdma_rx.Instance = DMA1_Stream4;
  348.                 dev->hdma_rx.Init.Request = DMA_REQUEST_UART5_RX;
  349.         }
  350.     else if(dev->idx == USART6){
  351.                 __HAL_RCC_DMA1_CLK_ENABLE();
  352.                 dev->hdma_rx.Instance = DMA1_Stream5;
  353.                 dev->hdma_rx.Init.Request = DMA_REQUEST_USART6_RX;
  354.         }
  355.     else if(dev->idx == UART7){
  356.                 __HAL_RCC_DMA1_CLK_ENABLE();
  357.                 dev->hdma_rx.Instance = DMA1_Stream6;
  358.                 dev->hdma_rx.Init.Request = DMA_REQUEST_UART7_RX;
  359.         }
  360.     else if(dev->idx == UART8){
  361.                 __HAL_RCC_DMA1_CLK_ENABLE();
  362.                 dev->hdma_rx.Instance = DMA1_Stream7;
  363.                 dev->hdma_rx.Init.Request = DMA_REQUEST_UART8_RX;
  364.         }
  365.     else
  366.     {
  367.         UART_DEBUG("Uart port error!");
  368.         return UART_SET_ERR;
  369.     }
  370.    
  371.     dev->hdma_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
  372.     dev->hdma_rx.Init.PeriphInc = DMA_PINC_DISABLE;
  373.     dev->hdma_rx.Init.MemInc = DMA_MINC_ENABLE;
  374.     dev->hdma_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
  375.     dev->hdma_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
  376.     dev->hdma_rx.Init.Mode = DMA_CIRCULAR;
  377.     dev->hdma_rx.Init.Priority = DMA_PRIORITY_LOW;
  378.     dev->hdma_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
  379.     dev->hdma_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
  380.     dev->hdma_rx.Init.MemBurst = DMA_MBURST_INC16;
  381.     dev->hdma_rx.Init.PeriphBurst = DMA_PBURST_INC16;
  382.     //按照STM32H750的勘误要求uart如果使用dma,对应的SxCR bit20必须置位
  383.     ((DMA_Stream_TypeDef *)(dev->hdma_rx.Instance))->CR |= 0x100000;       
  384.     if (HAL_DMA_Init(&(dev->hdma_rx)) != HAL_OK){return UART_SET_ERR;}
  385.         __HAL_LINKDMA(&(dev->huart),hdmarx,dev->hdma_rx);

  386.         return UART_OK;
  387. }

  388. /** ****************************************************************************
  389. * @brief 串口初始化
  390. * @param dev 设备对象
  391. * @param uart 串口
  392. * @param bps 波特率
  393. *******************************************************************************/
  394. uint8_t Uart_Init(UART_Device* dev,USART_TypeDef* uart,uint32_t bps,uint8_t* buf,size_t len)
  395. {
  396.         RCC_PeriphCLKInitTypeDef RCC_PeriphClkInit;
  397.        
  398.     dev->idx = uart;
  399.     dev->bps = bps;
  400.     dev->rbuf.len = len;
  401.     dev->rbuf.data = buf;

  402.         IoInit(dev);                        //初始化gpio
  403.            
  404.     if(dev->idx == LPUART1){
  405.                 RCC_PeriphClkInit.PeriphClockSelection          = RCC_PERIPHCLK_LPUART1;
  406.                 RCC_PeriphClkInit.Lpuart1ClockSelection  = RCC_LPUART1CLKSOURCE_D3PCLK1;
  407.                 HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit);
  408.                 __HAL_RCC_LPUART1_CLK_ENABLE();
  409.         }
  410.         else if(dev->idx == USART1){
  411.                 RCC_PeriphClkInit.PeriphClockSelection          = RCC_PERIPHCLK_USART16;
  412.                 RCC_PeriphClkInit.Usart16ClockSelection  = RCC_USART16CLKSOURCE_D2PCLK2;
  413.                 HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit);
  414.                 __HAL_RCC_USART1_CLK_ENABLE();
  415.         }
  416.         else if(dev->idx == USART2){
  417.                 RCC_PeriphClkInit.PeriphClockSelection          = RCC_PERIPHCLK_USART234578;
  418.                 RCC_PeriphClkInit.Usart234578ClockSelection  = RCC_USART234578CLKSOURCE_D2PCLK1;
  419.                 HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit);
  420.                 __HAL_RCC_USART2_CLK_ENABLE();
  421.         }
  422.     else if(dev->idx == USART3){
  423.                 RCC_PeriphClkInit.PeriphClockSelection          = RCC_PERIPHCLK_USART234578;
  424.                 RCC_PeriphClkInit.Usart234578ClockSelection  = RCC_USART234578CLKSOURCE_D2PCLK1;
  425.                 HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit);
  426.                 __HAL_RCC_USART3_CLK_ENABLE();
  427.         }
  428.     else if(dev->idx == UART4){
  429.                 RCC_PeriphClkInit.PeriphClockSelection          = RCC_PERIPHCLK_USART234578;
  430.                 RCC_PeriphClkInit.Usart234578ClockSelection  = RCC_USART234578CLKSOURCE_D2PCLK1;
  431.                 HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit);
  432.                 __HAL_RCC_UART4_CLK_ENABLE();
  433.         }
  434.     else if(dev->idx == UART5){
  435.                 RCC_PeriphClkInit.PeriphClockSelection          = RCC_PERIPHCLK_USART234578;
  436.                 RCC_PeriphClkInit.Usart234578ClockSelection  = RCC_USART234578CLKSOURCE_D2PCLK1;
  437.                 HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit);
  438.                 __HAL_RCC_UART5_CLK_ENABLE();
  439.         }
  440.     else if(dev->idx == USART6){
  441.                 RCC_PeriphClkInit.PeriphClockSelection          = RCC_PERIPHCLK_USART16;
  442.                 RCC_PeriphClkInit.Usart16ClockSelection  = RCC_USART16CLKSOURCE_D2PCLK2;
  443.                 HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit);
  444.                 __HAL_RCC_USART6_CLK_ENABLE();
  445.         }
  446.     else if(dev->idx == UART7){
  447.                 RCC_PeriphClkInit.PeriphClockSelection          = RCC_PERIPHCLK_USART234578;
  448.                 RCC_PeriphClkInit.Usart234578ClockSelection  = RCC_USART234578CLKSOURCE_D2PCLK1;
  449.                 HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit);
  450.                 __HAL_RCC_UART7_CLK_ENABLE();
  451.         }
  452.     else if(dev->idx == UART8){
  453.                 RCC_PeriphClkInit.PeriphClockSelection          = RCC_PERIPHCLK_USART234578;
  454.                 RCC_PeriphClkInit.Usart234578ClockSelection  = RCC_USART234578CLKSOURCE_D2PCLK1;
  455.                 HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit);
  456.                 __HAL_RCC_UART8_CLK_ENABLE();
  457.         }
  458.         dev->huart.Instance                                         = dev->idx;                                                //串口信息
  459.         dev->huart.Init.BaudRate                                 = dev->bps;                                                //波特率
  460.         dev->huart.Init.WordLength                                 = UART_WORDLENGTH_8B;                        //字长为8位数据格式
  461.         dev->huart.Init.StopBits                                 = UART_STOPBITS_1;                                //1bit停止位
  462.         dev->huart.Init.Parity                                         = UART_PARITY_NONE;                                //无奇偶校验位
  463.         dev->huart.Init.Mode                                         = UART_MODE_TX_RX;                                //收发模式
  464.         dev->huart.Init.HwFlowCtl                                 = UART_HWCONTROL_NONE;                        //无硬件流控
  465.         dev->huart.Init.OverSampling                         = UART_OVERSAMPLING_16;
  466.         dev->huart.Init.OneBitSampling                         = UART_ONE_BIT_SAMPLE_DISABLE;
  467.         dev->huart.Init.ClockPrescaler          = UART_PRESCALER_DIV1;
  468.         dev->huart.AdvancedInit.AdvFeatureInit         = UART_ADVFEATURE_NO_INIT;
  469.    
  470.         if (HAL_UART_Init(&(dev->huart)) != HAL_OK){return UART_SET_ERR;}
  471.     if (HAL_UARTEx_SetRxFifoThreshold(&(dev->huart),UART_RXFIFO_THRESHOLD_8_8) != HAL_OK){return UART_SET_ERR;}
  472.         if (HAL_UARTEx_DisableFifoMode(&(dev->huart)) != HAL_OK){return UART_SET_ERR;}

  473.         if (DmaInit(dev)!= HAL_OK){return UART_SET_ERR;}                                //初始化dma       
  474.         if (HAL_UART_Receive_DMA(&(dev->huart),dev->rbuf.data,dev->rbuf.len)!= HAL_OK){return UART_SET_ERR;}
  475.     Uart_ClearBuf(dev);
  476.    
  477.     return UART_OK;
  478. }
  479. /** ****************************************************************************
  480. * @brief 串口GPIO解绑
  481. * @param gpiox 端口号
  482. * @param gpio_pin 管脚号
  483. * @param alternate 复用模式
  484. * @note 此函数是用于适应GPIO宏定义格式
  485. *******************************************************************************/
  486. void Uart_GpioDeInit(GPIO_TypeDef* gpiox,uint16_t gpio_pin,uint8_t alternate)
  487. {
  488.     HAL_GPIO_DeInit(gpiox, gpio_pin);   
  489. }
  490. /** ****************************************************************************
  491. * @brief 串口解绑
  492. * @param dev 设备对象
  493. * @note 主要是用于配合boot模式使用
  494. *******************************************************************************/
  495. uint8_t Uart_DeInit(UART_Device* dev)
  496. {
  497.     if(dev->idx == LPUART1){
  498.         __HAL_RCC_LPUART1_CLK_DISABLE();
  499.         #if (defined COM0_RX) &&  (defined COM0_TX)
  500.         Uart_GpioDeInit(COM0_RX);
  501.         Uart_GpioDeInit(COM0_RX);
  502.         #else
  503.         UART_DEBUG("COM0 prot not define!");
  504.         #endif
  505.         }
  506.         else if(dev->idx == USART1){
  507.         __HAL_RCC_USART1_CLK_DISABLE();
  508.         #if (defined COM1_RX) &&  (defined COM1_TX)
  509.         Uart_GpioDeInit(COM1_RX);
  510.         Uart_GpioDeInit(COM1_TX);
  511.         #else
  512.         UART_DEBUG("COM1 prot not define!");
  513.         #endif
  514.         }
  515.         else if(dev->idx == USART2){
  516.                 __HAL_RCC_USART2_CLK_ENABLE();
  517.         #if (defined COM2_RX) &&  (defined COM2_TX)
  518.         Uart_GpioDeInit(COM2_RX);
  519.         Uart_GpioDeInit(COM2_TX);
  520.         #else
  521.         UART_DEBUG("COM2 prot not define!");
  522.         #endif
  523.     }
  524.     else if(dev->idx == USART3){
  525.         __HAL_RCC_USART3_CLK_DISABLE();
  526.         #if (defined COM3_RX) &&  (defined COM3_TX)
  527.         Uart_GpioDeInit(COM3_RX);
  528.         Uart_GpioDeInit(COM3_TX);
  529.         #else
  530.         UART_DEBUG("COM3 prot not define!");
  531.         #endif
  532.         }
  533.     else if(dev->idx == UART4){
  534.         __HAL_RCC_UART4_CLK_DISABLE();
  535.         #if (defined COM4_RX) &&  (defined COM4_TX)
  536.         Uart_GpioDeInit(COM4_RX);
  537.         Uart_GpioDeInit(COM4_TX);
  538.         #else
  539.         UART_DEBUG("COM4 prot not define!");
  540.         #endif
  541.         }
  542.     else if(dev->idx == UART5){
  543.         __HAL_RCC_UART5_CLK_DISABLE();
  544.         #if (defined COM5_RX) &&  (defined COM5_TX)
  545.         Uart_GpioDeInit(COM5_RX);
  546.         Uart_GpioDeInit(COM5_TX);
  547.         #else
  548.         UART_DEBUG("COM5 prot not define!");
  549.         #endif
  550.         }
  551.     else if(dev->idx == USART6){
  552.         __HAL_RCC_USART6_CLK_DISABLE();
  553.         #if (defined COM6_RX) &&  (defined COM6_TX)
  554.         Uart_GpioDeInit(COM6_RX);
  555.         Uart_GpioDeInit(COM6_TX);
  556.         #else
  557.         UART_DEBUG("COM6 prot not define!");
  558.         #endif
  559.         }
  560.     else if(dev->idx == UART7){
  561.         __HAL_RCC_UART7_CLK_DISABLE();
  562.         #if (defined COM7_RX) &&  (defined COM7_TX)
  563.         Uart_GpioDeInit(COM7_RX);
  564.         Uart_GpioDeInit(COM7_TX);
  565.         #else
  566.         UART_DEBUG("COM7 prot not define!");
  567.         #endif
  568.         }
  569.     else if(dev->idx == UART8){
  570.         __HAL_RCC_UART8_CLK_DISABLE();
  571.         #if (defined COM8_RX) &&  (defined COM8_TX)
  572.         Uart_GpioDeInit(COM8_RX);
  573.         Uart_GpioDeInit(COM8_TX);
  574.         #else
  575.         UART_DEBUG("COM8 prot not define!");
  576.         #endif
  577.         }
  578.     HAL_DMA_DeInit(&(dev->hdma_rx));
  579.    
  580.     return 0;
  581. }


  582. /*********************************END OF FILE**********************************/
复制代码



uart.h

3.6 KB, 下载次数: 0

uart.c

20.84 KB, 下载次数: 0

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-12 09:48 , Processed in 0.265344 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表