打印
[牛人杂谈]

UART 初始化

[复制链接]
1871|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
yiy|  楼主 | 2017-4-16 20:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
      新唐的M0/M4 UART都有16级或者64级FIFO,用来缓存UART数据的收/发。例如:如果RX FIFO 中断触发级别设为14,UART接收14个字节才会发生RDA(接收数据可得)中断。这样可以降低 CPU的负载。上面的情况,如果RX只接收到10个字节怎么办呢?这时候就要用到接收超时中断。当RXFIFO中收到1个字节以后,定时器就开始计数,如果定时器超时都没有再收到下一个字节就会发生接收超时中断(RTO)。

沙发
yiy|  楼主 | 2017-4-16 20:04 | 只看该作者
每个IP的初始化都需要先初始化时钟,然后才是IP功能初始化。初始化UART之前需要使能要用的晶振,然后选择时钟源并使能时钟。最后将UART用到的引脚切换为UART功能。
void UART0_Init()
{
    /* UART选择HIRC做时钟源 */
  CLK->CLKSEL1 = (CLK->CLKSEL1 &~CLK_CLKSEL1_UART_S_Msk)  |CLK_CLKSEL1_UART_S_HIRC;
    /* 使能UART0 IP的时钟 */
    CLK->APBCLK |= CLK_APBCLK_UART0_EN;
    /* PB13用作UART0 接收,PB14用作UART0发送 */
    SYS->PB_H_MFP &=~(SYS_PB_H_MFP_PB13_MFP_Msk | SYS_PB_H_MFP_PB14_MFP_Msk);
   SYS->PB_H_MFP |= (SYS_PB_H_MFP_PB13_MFP_UART0_RX |SYS_PB_H_MFP_PB14_MFP_UART0_TX);     /* Init UART0  */
UART_Open(UART0, 115200);/*默认数据长度为8bit,没有奇偶校验,1个停止位*/
    /*初始化UART1,波特率9600,数据长度8bit,1个停止位,偶校验*/
    UART_SetLine_Config(UART1, 9600, UART_WORD_LEN_8, UART_PARITY_EVEN,UART_STOP_BIT_1); }


这里为了大家看得清楚,把选择时钟源,使能时钟,配置多功能引脚都放到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口打印。

使用特权

评论回复
板凳
yiy|  楼主 | 2017-4-16 20:05 | 只看该作者
如果想使用中断接收数据,代码如下:
  
void  UART0_Init() {
  
/* 选择UART时钟源 */
  
     CLK->CLKSEL1 = (CLK->CLKSEL1 & ~CLK_CLKSEL1_UART_S_Msk)  | CLK_CLKSEL1_UART_S_HIRC;     /* 使能UART0 IP的时钟 */
  
    CLK->APBCLK |=  CLK_APBCLK_UART0_EN;
  
    /* PB13用作UART0 接收,PB14用作UART0发送 */
  
    SYS->PB_H_MFP &=  ~(SYS_PB_H_MFP_PB13_MFP_Msk | SYS_PB_H_MFP_PB14_MFP_Msk);
  
    SYS->PB_H_MFP |=  (SYS_PB_H_MFP_PB13_MFP_UART0_RX | SYS_PB_H_MFP_PB14_MFP_UART0_TX);
  
  
    /* Init UART0   */
  
UART_Open(UART0, 115200);/*默认数据长度为8bit,没有奇偶校验,1个停止位*/
  
    /*初始化UART1,波特率9600,数据长度8bit,1个停止位,偶校验*/
  
     UART_SetLine_Config(UART1, 9600, UART_WORD_LEN_8, UART_PARITY_EVEN,  UART_STOP_BIT_1);
  
    /*设置接收超时时间为40,单位波特率*/
  
    UART_SetTimeoutCnt(UART0,  40);
  
    /*设置接收FIFO触发级别为14B*/
  
     UART_SET_RX_FIFO_INTTRGLV(UART0, UART_TLCTL_RFITL_14BYTES);
  
/*使能接收FIFO 阀值中断,和接收超时中断*/
UART_ENABLE_INT(UART0, (UART_IER_RDA_IE_Msk |UART_IER_RTO_IE_Msk));
    NVIC_EnableIRQ(UART0_IRQn);
}
/*UART0中断处理函数*/
voidUART0_IRQHandler(void)
{    uint8_t u8InChar=0xFF;    uint32_t u32IntSts= UART0->ISR;
    /*发生接收阀值中断或者接收超时中断*/
   if(u32IntSts & (UART_ISR_RDA_IS_Msk| UART_ISR_RTO_IS_Msk)) {         
        /* 读走接收FIFO中所有的数据,直到接收FIFO为空 */
        while(UART_GET_RX_EMPTY(UART0)==0){             /* 从接收FIFO中读一个数据 */
           u8InChar = UART_READ(UART0);  }
}
}

使用特权

评论回复
地板
yiy|  楼主 | 2017-4-16 20:07 | 只看该作者
UART IP有个复位函数:SYS_ResetModule(UART0_RST); 其实新唐的芯片每个IP都有单独的复位控制,用来复位整个IP的逻辑。

使用特权

评论回复
5
稳稳の幸福| | 2017-4-16 22:22 | 只看该作者
这个应用最多的外设,学不好真不能算学会了。

使用特权

评论回复
6
zhuomuniao110| | 2017-4-16 23:06 | 只看该作者
这些都在官方出品的例程里有见过,不过没有这么详细的讲解。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

yiy

92

主题

1701

帖子

4

粉丝