zoukankan      html  css  js  c++  java
  • M0 M4之UART初始化

    新唐的M0/M4 UART都有16级或者64级FIFO,用来缓存UART数据的收/发。例如:如果RX FIFO中断触发级别设为14,UART接收14个字节才会发生RDA(接收数据可得)中断。这样可以降低CPU的loading。上面的情况,如果RX只接收到10个字节怎么办呢?这时候就要用到接收超时中断。当RX FIFO中收到1个字节以后,定时器就开始计数,如果定时器超时都没有再收到下一个字节就会发生接收超时中断(RTO)。
    每个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);
    
    }
    
    UART_Open会根据UART选择的时钟源计算波特率。
    上面的代码执行之后,UART_WRITE(UART0, 0x31)就会从UART TX引脚发送0x31了。如果要使用printf打印信息,keil project中加入retarget.c就可以,然后由宏定义#define DEBUG_PORT UART0决定printf从哪个UART口打印。
    如果想使用中断接收数据,代码如下:
    
    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中断处理函数*/
    
    void UART0_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);
    
    }
    
    }
    
    }

    UART IP有个复位函数:SYS_ResetModule(UART0_RST); 其实新唐的芯片每个IP都有单独的复位控制。什么时候需要复位UART0呢?如果该代码是通过CPU reset执行到的,那原本UART可能在工作,RX FIFO中可能有数据,可能会发生中断等等一些无法预估的事情,这时候最好复位一下UART IP的逻辑。

  • 相关阅读:
    flask 知识积累
    python中下划线
    pipenv知识积累
    shell知识积累
    AttributeError: type object 'testClass' has no attribute 'testMothod'
    python知识积累
    补全爬取的url
    linux 的基本命令
    Python里的拷贝
    关于第一次java课的感想
  • 原文地址:https://www.cnblogs.com/zhugeanran/p/8677477.html
Copyright © 2011-2022 走看看