usart.c.bak 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. #include "usart.h"
  2. #include "delay.h"
  3. //////////////////////////////////////////////////////////////////////////////////
  4. //如果使用os,则包括下面的头文件即可.
  5. #if SYSTEM_SUPPORT_OS
  6. #include "includes.h" //os 使用
  7. #endif
  8. //////////////////////////////////////////////////////////////////////////////////
  9. //本程序只供学习使用,未经作者许可,不得用于其它任何用途
  10. //ALIENTEK STM32F407开发板
  11. //串口3初始化
  12. //正点原子@ALIENTEK
  13. //技术论坛:www.openedv.com
  14. //修改日期:2017/4/6
  15. //版本:V1.5
  16. //版权所有,盗版必究。
  17. //Copyright(C) 广州市星翼电子科技有限公司 2009-2019
  18. //All rights reserved
  19. //********************************************************************************
  20. //V1.0修改说明
  21. //////////////////////////////////////////////////////////////////////////////////
  22. //加入以下代码,支持printf函数,而不需要选择use MicroLIB
  23. //#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
  24. #if 1
  25. #pragma import(__use_no_semihosting)
  26. //标准库需要的支持函数
  27. struct __FILE
  28. {
  29. int handle;
  30. };
  31. FILE __stdout;
  32. //定义_sys_exit()以避免使用半主机模式
  33. void _sys_exit(int x)
  34. {
  35. x = x;
  36. }
  37. //重定义fputc函数
  38. int fputc(int ch, FILE *f)
  39. {
  40. while((USART3->SR&0X40)==0);//循环发送,直到发送完毕
  41. USART3->DR = (u8) ch;
  42. return ch;
  43. }
  44. #endif
  45. //串口2中断服务程序
  46. //注意,读取USARTx->SR能避免莫名其妙的错误
  47. u8 USART2_RX_BUF[USART2_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
  48. u16 USART2_RX_STA=0; //接收状态标记
  49. UART_HandleTypeDef huart2; //USART3句柄(用于RS485)
  50. u8 usart2_aRxBuffer[RXBUFFERSIZE];//HAL库使用的串口接收缓冲
  51. #if EN_USART3_RX //如果使能了接收
  52. //串口3中断服务程序
  53. //注意,读取USARTx->SR能避免莫名其妙的错误
  54. u8 USART3_RX_BUF[USART3_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
  55. UART_HandleTypeDef huart3; //USART3句柄(用于RS485)
  56. //接收状态
  57. //bit15, 接收完成标志
  58. //bit14, 接收到0x0d
  59. //bit13~0, 接收到的有效字节数目
  60. u16 USART3_RX_STA=0; //接收状态标记
  61. u8 usart3_aRxBuffer[RXBUFFERSIZE];//HAL库使用的串口接收缓冲
  62. UART_HandleTypeDef UART2_Handler; //UART句柄
  63. UART_HandleTypeDef UART3_Handler; //UART句柄
  64. //******************************************
  65. //初始化IO 串口2
  66. //bound:波特率
  67. //******************************************
  68. void uart2_init(u32 bound)
  69. {
  70. //UART 初始化设置
  71. UART3_Handler.Instance=USART2; //USART1
  72. UART3_Handler.Init.BaudRate=bound; //波特率
  73. UART3_Handler.Init.WordLength=UART_WORDLENGTH_8B; //字长为8位数据格式
  74. UART3_Handler.Init.StopBits=UART_STOPBITS_1; //一个停止位
  75. UART3_Handler.Init.Parity=UART_PARITY_NONE; //无奇偶校验位
  76. UART3_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE; //无硬件流控
  77. UART3_Handler.Init.Mode=UART_MODE_TX_RX; //收发模式
  78. HAL_UART_Init(&UART2_Handler); //HAL_UART_Init()会使能UART3
  79. HAL_UART_Receive_IT(&UART2_Handler, (u8 *)usart2_aRxBuffer, RXBUFFERSIZE);//该函数会开启接收中断:标志位UART_IT_RXNE,并且设置接收缓冲以及接收缓冲接收最大数据量
  80. }
  81. //******************************************
  82. //初始化IO 串口3
  83. //bound:波特率
  84. //******************************************
  85. void uart3_init(u32 bound)
  86. {
  87. //UART 初始化设置
  88. UART3_Handler.Instance=USART3; //USART1
  89. UART3_Handler.Init.BaudRate=bound; //波特率
  90. UART3_Handler.Init.WordLength=UART_WORDLENGTH_8B; //字长为8位数据格式
  91. UART3_Handler.Init.StopBits=UART_STOPBITS_1; //一个停止位
  92. UART3_Handler.Init.Parity=UART_PARITY_NONE; //无奇偶校验位
  93. UART3_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE; //无硬件流控
  94. UART3_Handler.Init.Mode=UART_MODE_TX_RX; //收发模式
  95. HAL_UART_Init(&UART3_Handler); //HAL_UART_Init()会使能UART3
  96. HAL_UART_Receive_IT(&UART3_Handler, (u8 *)usart3_aRxBuffer, RXBUFFERSIZE);//该函数会开启接收中断:标志位UART_IT_RXNE,并且设置接收缓冲以及接收缓冲接收最大数据量
  97. }
  98. //UART底层初始化,时钟使能,引脚配置,中断配置
  99. //此函数会被HAL_UART_Init()调用
  100. //huart:串口句柄
  101. void HAL_UART_MspInit(UART_HandleTypeDef *huart)
  102. {
  103. //GPIO端口设置
  104. GPIO_InitTypeDef GPIO_Initure;
  105. if(huart->Instance==USART2)//如果是串口2,进行串口2 MSP初始化
  106. {
  107. __HAL_RCC_GPIOA_CLK_ENABLE(); //使能GPIOA时钟
  108. __HAL_RCC_USART2_CLK_ENABLE(); //使能USART3时钟
  109. GPIO_Initure.Pin=GPIO_PIN_2; //PA2 usart2_tx
  110. GPIO_Initure.Mode=GPIO_MODE_AF_PP; //复用推挽输出
  111. GPIO_Initure.Pull=GPIO_PULLUP; //上拉
  112. GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;//高速
  113. HAL_GPIO_Init(GPIOA,&GPIO_Initure); //初始化PA2
  114. GPIO_Initure.Pin=GPIO_PIN_3; //PA3
  115. GPIO_Initure.Mode=GPIO_MODE_AF_INPUT; //模式要设置为复用输入模式!
  116. HAL_GPIO_Init(GPIOA,&GPIO_Initure); //初始化PA2
  117. __HAL_UART_ENABLE_IT(&UART2_Handler,UART_IT_RXNE);//开启接收中断
  118. HAL_NVIC_EnableIRQ(USART2_IRQn); //使能USART3中断通道
  119. HAL_NVIC_SetPriority(USART2_IRQn,1,1); //抢占优先级3,子优先级3
  120. }
  121. if(huart->Instance==USART3)//如果是串口3,进行串口3 MSP初始化
  122. {
  123. __HAL_RCC_GPIOB_CLK_ENABLE(); //使能GPIOB时钟
  124. __HAL_RCC_GPIOC_CLK_ENABLE(); //使能GPIOC时钟
  125. __HAL_RCC_USART3_CLK_ENABLE(); //使能USART3时钟
  126. GPIO_Initure.Pin=GPIO_PIN_10; //PB10 usart3_tx
  127. GPIO_Initure.Mode=GPIO_MODE_AF_PP; //复用推挽输出
  128. GPIO_Initure.Pull=GPIO_PULLUP; //上拉
  129. GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;//高速
  130. HAL_GPIO_Init(GPIOB,&GPIO_Initure); //初始化PB10
  131. GPIO_Initure.Pin=GPIO_PIN_11; //PB11
  132. GPIO_Initure.Mode=GPIO_MODE_AF_INPUT; //模式要设置为复用输入模式!
  133. HAL_GPIO_Init(GPIOB,&GPIO_Initure); //初始化PB11
  134. GPIO_Initure.Pin = GPIO_PIN_13; //485 发送接收
  135. GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP;
  136. GPIO_Initure.Pull = GPIO_NOPULL;
  137. GPIO_Initure.Speed = GPIO_SPEED_FREQ_HIGH;
  138. HAL_GPIO_Init(GPIOC, &GPIO_Initure);
  139. #if EN_USART3_RX
  140. __HAL_UART_ENABLE_IT(&UART3_Handler,UART_IT_RXNE);//开启接收中断
  141. HAL_NVIC_EnableIRQ(USART3_IRQn); //使能USART3中断通道
  142. HAL_NVIC_SetPriority(USART3_IRQn,2,2); //抢占优先级3,子优先级3
  143. #endif
  144. Usart_TX_Set(0); //设置为接收模式
  145. }
  146. }
  147. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
  148. {
  149. if(huart->Instance==USART2)//如果是串口2
  150. {
  151. if((USART2_RX_STA&0x8000)==0)//接收未完成
  152. {
  153. if(USART2_RX_STA&0x4000)//接收到了0x0d
  154. {
  155. if(usart2_aRxBuffer[0]!=0x0a)USART2_RX_STA=0;//接收错误,重新开始
  156. else USART2_RX_STA|=0x8000; //接收完成了
  157. }
  158. else //还没收到0X0D
  159. {
  160. if(usart2_aRxBuffer[0]==0x0d)USART2_RX_STA|=0x4000;
  161. else
  162. {
  163. USART2_RX_BUF[USART2_RX_STA&0X3FFF]=usart2_aRxBuffer[0] ;
  164. USART2_RX_STA++;
  165. if(USART2_RX_STA>(USART2_REC_LEN-1))USART2_RX_STA=0;//接收数据错误,重新开始接收
  166. }
  167. }
  168. }
  169. }
  170. if(huart->Instance==USART3)//如果是串口3
  171. {
  172. if((USART3_RX_STA&0x8000)==0)//接收未完成
  173. {
  174. if(USART3_RX_STA&0x4000)//接收到了0x0d
  175. {
  176. if(usart3_aRxBuffer[0]!=0x0a)USART3_RX_STA=0;//接收错误,重新开始
  177. else USART3_RX_STA|=0x8000; //接收完成了
  178. }
  179. else //还没收到0X0D
  180. {
  181. if(usart3_aRxBuffer[0]==0x0d)USART3_RX_STA|=0x4000;
  182. else
  183. {
  184. USART3_RX_BUF[USART3_RX_STA&0X3FFF]=usart3_aRxBuffer[0] ;
  185. USART3_RX_STA++;
  186. if(USART3_RX_STA>(USART3_REC_LEN-1))USART3_RX_STA=0;//接收数据错误,重新开始接收
  187. }
  188. }
  189. }
  190. }
  191. }
  192. //串口2中断服务程序
  193. void USART2_IRQHandler(void)
  194. {
  195. u32 timeout=0;
  196. #if SYSTEM_SUPPORT_OS //使用OS
  197. OSIntEnter();
  198. #endif
  199. HAL_UART_IRQHandler(&UART2_Handler); //调用HAL库中断处理公用函数
  200. timeout=0;
  201. while (HAL_UART_GetState(&UART2_Handler) != HAL_UART_STATE_READY)//等待就绪
  202. {
  203. timeout++;////超时处理
  204. if(timeout>HAL_MAX_DELAY) break;
  205. }
  206. timeout=0;
  207. while(HAL_UART_Receive_IT(&UART2_Handler, (u8 *)usart2_aRxBuffer, RXBUFFERSIZE) != HAL_OK)//一次处理完成之后,重新开启中断并设置RxXferCount为1
  208. {
  209. timeout++; //超时处理
  210. if(timeout>HAL_MAX_DELAY) break;
  211. }
  212. #if SYSTEM_SUPPORT_OS //使用OS
  213. OSIntExit();
  214. #endif
  215. }
  216. //串口3中断服务程序
  217. void USART3_IRQHandler(void)
  218. {
  219. u32 timeout=0;
  220. #if SYSTEM_SUPPORT_OS //使用OS
  221. OSIntEnter();
  222. #endif
  223. HAL_UART_IRQHandler(&UART3_Handler); //调用HAL库中断处理公用函数
  224. timeout=0;
  225. while (HAL_UART_GetState(&UART3_Handler) != HAL_UART_STATE_READY)//等待就绪
  226. {
  227. timeout++;////超时处理
  228. if(timeout>HAL_MAX_DELAY) break;
  229. }
  230. timeout=0;
  231. while(HAL_UART_Receive_IT(&UART3_Handler, (u8 *)usart3_aRxBuffer, RXBUFFERSIZE) != HAL_OK)//一次处理完成之后,重新开启中断并设置RxXferCount为1
  232. {
  233. timeout++; //超时处理
  234. if(timeout>HAL_MAX_DELAY) break;
  235. }
  236. #if SYSTEM_SUPPORT_OS //使用OS
  237. OSIntExit();
  238. #endif
  239. }
  240. #endif
  241. //******************************************
  242. //RS485模式控制.
  243. //Ren:1,接收;0,发送.
  244. //******************************************
  245. void Usart_TX_Set(uint8_t Ren)
  246. {
  247. uint8_t i;
  248. i=Ren;
  249. if(i==0)
  250. {
  251. PCout(13)=0;
  252. }
  253. else
  254. {
  255. PCout(13)=1;
  256. }
  257. }
  258. //******************************************
  259. //RS485发送字符串.
  260. //******************************************
  261. void Usart_Send_Str_Data(char *str)
  262. {
  263. Usart_TX_Set(1); //设置为发送模式
  264. delay_us(50);
  265. printf(str);
  266. Usart_TX_Set(0); //设置为接收模式
  267. delay_us(50);
  268. }
  269. //******************************************
  270. //RS485发送len个字节.
  271. //buf:发送区首地址
  272. //len:发送的字节数(为了和本代码的接收匹配,这里建议不要超过64个字节)
  273. //******************************************
  274. void Usart_Send_Data(uint8_t *buf,uint8_t len)
  275. {
  276. Usart_TX_Set(0); //设置为发送模式
  277. delay_ms(100);
  278. HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_1);
  279. // HAL_UART_Transmit(&huart3,buf,len,1000);//串口3发送数据
  280. Usart_TX_Set(1); //设置为接收模式
  281. delay_ms(50);
  282. }
  283. //中断缓存串口数据
  284. #define UART_BUFF_SIZE 1024
  285. volatile uint16_t uart_p = 0;
  286. uint8_t uart_buff[UART_BUFF_SIZE];
  287. /*
  288. void RS485_IRQHandler(void)
  289. {
  290. if(uart_p<UART_BUFF_SIZE)
  291. {
  292. if(USART_GetITStatus(huart3, USART_IT_RXNE) != RESET)
  293. {
  294. uart_buff[uart_p] = USART_ReceiveData(huart3);
  295. uart_p++;
  296. USART_ClearITPendingBit(&huart3, USART_IT_RXNE);
  297. }
  298. }
  299. else
  300. {
  301. USART_ClearITPendingBit(huart3, USART_IT_RXNE);
  302. // clean_rebuff();
  303. }
  304. }
  305. */
  306. //获取接收到的数据和长度
  307. char *get_rebuff(uint16_t *len)
  308. {
  309. *len = uart_p;
  310. return (char *)&uart_buff;
  311. }
  312. //清空缓冲区
  313. void clean_rebuff(void)
  314. {
  315. uint16_t i=UART_BUFF_SIZE+1;
  316. uart_p = 0;
  317. while(i)
  318. uart_buff[--i]=0;
  319. }