打印
[牛人杂谈]

UART 初始化

[复制链接]
3646|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功能。

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); }


沙发
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 | 只看该作者
如果想使用中断接收数据,代码如下:
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都有单独的复位控制,用来复位整个IP的逻辑。

使用特权

评论回复
地板
lovecat2015| | 2016-5-15 22:40 | 只看该作者
那么在低功耗模式下,这个波特率能够最高达到多少呢

使用特权

评论回复
5
ccw1986| | 2016-5-16 22:52 | 只看该作者
uart属于异步通信,对时钟的要求低些吧

使用特权

评论回复
6
734774645| | 2016-5-17 00:02 | 只看该作者
UART_Open会根据UART选择的时钟源计算波特率。

使用特权

评论回复
7
643757107| | 2016-5-17 14:21 | 只看该作者
串口的初始化很容易,可是串口的用法有很多种

使用特权

评论回复
8
稳稳の幸福| | 2016-5-17 20:37 | 只看该作者
lovecat2015 发表于 2016-5-15 22:40
那么在低功耗模式下,这个波特率能够最高达到多少呢

低功耗模式下是不发送的。恢复后才能发送。就跟睡觉后没法走路,想走路先睡醒

使用特权

评论回复
9
zhuomuniao110|  楼主 | 2016-5-22 23:16 | 只看该作者
初始化UART之前需要使能要用的晶振,然后选择时钟源并使能时钟。

使用特权

评论回复
10
598330983| | 2016-5-23 19:42 | 只看该作者
  UART_SetLine_Config(UART1, 9600, UART_WORD_LEN_8, UART_PARITY_EVEN, UART_STOP_BIT_1); }
这个函数真是屌爆了,一个函数搞定了好多配置。

使用特权

评论回复
11
IversonCar| | 2016-5-25 17:34 | 只看该作者
时钟源的选择和波特率的设定有很大的关系

使用特权

评论回复
12
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);

使用特权

评论回复
13
xuechengchang| | 2017-4-24 11:12 | 只看该作者
UART_SET_RX_FIFO_INTTRGLV(UART0, UART_TLCTL_RFITL_14BYTES); 这个函数 NANO130库里没有呢?怎么回事,请指教

使用特权

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

本版积分规则

207

主题

3379

帖子

10

粉丝