[牛人杂谈] UART 初始化

[复制链接]
3932|12
 楼主| zhuomuniao110 发表于 2016-5-15 11:51 | 显示全部楼层 |阅读模式
新唐的M0/M4 UART都有16级或者64级FIFO,用来缓存UART数据的收/发。例如:如果RX FIFO 中断触发级别设为14,UART接收14个字节才会发生RDA(接收数据可得)中断。这样可以降低 CPU的负载。上面的情况,如果RX只接收到10个字节怎么办呢?这时候就要用到接收超时中断。当RXFIFO中收到1个字节以后,定时器就开始计数,如果定时器超时都没有再收到下一个字节就会发生接收超时中断(RTO)。
每个IP的初始化都需要先初始化时钟,然后才是IP功能初始化。初始化UART之前需要使能要用的晶振,然后选择时钟源并使能时钟。最后将UART用到的引脚切换为UART功能。

  1. void UART0_Init()
  2. {
  3.     /* UART选择HIRC做时钟源 */
  4.     CLK->CLKSEL1 = (CLK->CLKSEL1 & ~CLK_CLKSEL1_UART_S_Msk)  | CLK_CLKSEL1_UART_S_HIRC;
  5.     /* 使能UART0 IP的时钟 */
  6.     CLK->APBCLK |= CLK_APBCLK_UART0_EN;
  7.     /* PB13用作UART0 接收,PB14用作UART0发送 */
  8.     SYS->PB_H_MFP &= ~(SYS_PB_H_MFP_PB13_MFP_Msk | SYS_PB_H_MFP_PB14_MFP_Msk);
  9.     SYS->PB_H_MFP |= (SYS_PB_H_MFP_PB13_MFP_UART0_RX | SYS_PB_H_MFP_PB14_MFP_UART0_TX);     /* Init UART0  */
  10. UART_Open(UART0, 115200);/*默认数据长度为8bit,没有奇偶校验,1个停止位*/
  11.     /*初始化UART1,波特率9600,数据长度8bit,1个停止位,偶校验*/
  12.     UART_SetLine_Config(UART1, 9600, UART_WORD_LEN_8, UART_PARITY_EVEN, UART_STOP_BIT_1); }


 楼主| zhuomuniao110 发表于 2016-5-15 11:51 | 显示全部楼层
这里为了大家看得清楚,把选择时钟源,使能时钟,配置多功能引脚都放到UART0_Init函数里面了。其实这部分代码大家随意,想放到Sys_Init也行。
UART_Open会根据UART选择的时钟源计算波特率。会用到函数SystemCoreClockUpdate();更新过的变量。
上面的代码执行之后,UART_WRITE(UART0, 0x31)就会从UART TX引脚发送0x31了。如果要使用printf打印信息,keil project中加入retarget.c就可以,然后由宏定义#defineDEBUG_PORT UART0决定printf从哪个UART口打印。

 楼主| zhuomuniao110 发表于 2016-5-15 11:52 | 显示全部楼层
如果想使用中断接收数据,代码如下:
  1. void UART0_Init() {
  2. /* 选择UART时钟源 */
  3.     CLK->CLKSEL1 = (CLK->CLKSEL1 & ~CLK_CLKSEL1_UART_S_Msk)  | CLK_CLKSEL1_UART_S_HIRC;     /* 使能UART0 IP的时钟 */
  4.     CLK->APBCLK |= CLK_APBCLK_UART0_EN;
  5.     /* PB13用作UART0 接收,PB14用作UART0发送 */
  6.     SYS->PB_H_MFP &= ~(SYS_PB_H_MFP_PB13_MFP_Msk | SYS_PB_H_MFP_PB14_MFP_Msk);
  7.     SYS->PB_H_MFP |= (SYS_PB_H_MFP_PB13_MFP_UART0_RX | SYS_PB_H_MFP_PB14_MFP_UART0_TX);

  8.     /* Init UART0  */
  9. UART_Open(UART0, 115200);/*默认数据长度为8bit,没有奇偶校验,1个停止位*/
  10.     /*初始化UART1,波特率9600,数据长度8bit,1个停止位,偶校验*/
  11.     UART_SetLine_Config(UART1, 9600, UART_WORD_LEN_8, UART_PARITY_EVEN, UART_STOP_BIT_1);
  12.     /*设置接收超时时间为40,单位波特率*/
  13.     UART_SetTimeoutCnt(UART0, 40);
  14.     /*设置接收FIFO触发级别为14B*/
  15.     UART_SET_RX_FIFO_INTTRGLV(UART0, UART_TLCTL_RFITL_14BYTES);
  16. /*使能接收FIFO 阀值中断,和接收超时中断*/
  17. UART_ENABLE_INT(UART0, (UART_IER_RDA_IE_Msk | UART_IER_RTO_IE_Msk));
  18.     NVIC_EnableIRQ(UART0_IRQn);
  19. }
  20. /*UART0中断处理函数*/
  21. void UART0_IRQHandler(void)
  22. {     uint8_t u8InChar=0xFF;     uint32_t u32IntSts= UART0->ISR;
  23.     /*发生接收阀值中断或者接收超时中断*/
  24.     if(u32IntSts & (UART_ISR_RDA_IS_Msk| UART_ISR_RTO_IS_Msk)) {        
  25.         /* 读走接收FIFO中所有的数据,直到接收FIFO为空 */
  26.         while(UART_GET_RX_EMPTY(UART0)==0) {             /* 从接收FIFO中读一个数据 */
  27.             u8InChar = UART_READ(UART0);  }
  28. }
  29. }

UART IP有个复位函数:SYS_ResetModule(UART0_RST); 其实新唐的芯片每个IP都有单独的复位控制,用来复位整个IP的逻辑。
lovecat2015 发表于 2016-5-15 22:40 | 显示全部楼层
那么在低功耗模式下,这个波特率能够最高达到多少呢
ccw1986 发表于 2016-5-16 22:52 | 显示全部楼层
uart属于异步通信,对时钟的要求低些吧
734774645 发表于 2016-5-17 00:02 | 显示全部楼层
UART_Open会根据UART选择的时钟源计算波特率。
643757107 发表于 2016-5-17 14:21 | 显示全部楼层
串口的初始化很容易,可是串口的用法有很多种
稳稳の幸福 发表于 2016-5-17 20:37 | 显示全部楼层
lovecat2015 发表于 2016-5-15 22:40
那么在低功耗模式下,这个波特率能够最高达到多少呢

低功耗模式下是不发送的。恢复后才能发送。就跟睡觉后没法走路,想走路先睡醒
 楼主| zhuomuniao110 发表于 2016-5-22 23:16 | 显示全部楼层
初始化UART之前需要使能要用的晶振,然后选择时钟源并使能时钟。
598330983 发表于 2016-5-23 19:42 | 显示全部楼层
  UART_SetLine_Config(UART1, 9600, UART_WORD_LEN_8, UART_PARITY_EVEN, UART_STOP_BIT_1); }
这个函数真是屌爆了,一个函数搞定了好多配置。
IversonCar 发表于 2016-5-25 17:34 | 显示全部楼层
时钟源的选择和波特率的设定有很大的关系
gejigeji521 发表于 2016-5-25 23:43 | 显示全部楼层
/*初始化UART1,波特率9600,数据长度8bit,1个停止位,偶校验*/
    UART_SetLine_Config(UART1, 9600, UART_WORD_LEN_8, UART_PARITY_EVEN, UART_STOP_BIT_1);
xuechengchang 发表于 2017-4-24 11:12 | 显示全部楼层
UART_SET_RX_FIFO_INTTRGLV(UART0, UART_TLCTL_RFITL_14BYTES); 这个函数 NANO130库里没有呢?怎么回事,请指教
您需要登录后才可以回帖 登录 | 注册

本版积分规则

233

主题

3529

帖子

11

粉丝
快速回复 在线客服 返回列表 返回顶部