今天开始学习TRK-KEA64自带的例程Lab1:UART,其功能就是接收PC端发送过来的字符后将其发送至PC端(echo),主要的参考资料有AN4942 Getting Started with Kinetis EA series MCUs, KEA64 Sub-Family Reference Manual和开发板自带的例程Lab1 UART。
int main(void)
{
UINT32 counter = 0;
Clk_Init(); /* Configure clocks to run at 20 Mhz*/
UART_Init(); /*Initialize Uart 2 at 9600 bauds */
Uart_SetCallback(Uart_Interrupt); /* Set the callback function that the UART driver will call when receiving a char */
NVIC_EnableIRQ(UART2_IRQn); /* Enable UART2 interrupt*/
for(;;) {
counter++;
}
主程序:
1. 配置系统时钟,主要调用的模块是ICS(Internal Clock Source)来配置FLL(Frequecny Locked Loop);
void Clk_Init()
ICS->C1|=ICS_C1_IRCLKEN_MASK; /* Enable the internal reference clock*/
ICS->C3= 0x50; /* Reference clock frequency = 39.0625 KHz*/
while(!(ICS->S & ICS_S_LOCK_MASK)); /* Wait for PLL lock, now running at 40 MHz (1024 * 39.0625Khz) */
ICS->C2|=ICS_C2_BDIV(1) ; /*BDIV=2, Bus clock = 20 MHz*/
1)使能内部RC时钟;
2)这里不知道为什么配置成0x50??,fsl_automcu_stefan帮忙解释一下,谢谢
3)等待FLL Lock;
4)配置总线时钟20M
2. 配置UART:
1)首先调用SIM(System Integration Moduel)使能UART2模块的总线时钟(KEA中各种外设上电复位之后处于Disable状态以降低功耗,我们只需使能使用到的模块);
2)UART模式:8bit, No Parity, 1 Stop bit, Baud Rate 9600;
3)使能UART发送和接收模块;
4)使能UART接收中断(UART接收采用中断模式,发送则采用查询)。
3. 设置UART接收中断的回调函数,即将接收的字符通过UART发送出去
void Uart_Interrupt (UINT8 data)
Uart_SendChar(data); /* Echos data that is received*/
void Uart_SendChar(UINT8 send)
while((UART2->S1&UART_S1_TDRE_MASK)==0); /* Wait for transmit buffer to be empty*/
(void)UART2->S1; /* Read UART2_S1 register*/
UART2->D=send; /* Send data*/
1)等待UART2状态寄存器1中的TDRE(Transmit Data Register Empty Flag)置1;
2)读取UART2 状态寄存器1来清除TDRE标志(To clear TDRE, read UART_S1 with TDRE set and then write to the UART data register (UART_D)),所以只有将数据写入数据寄存器后TDRE 才会清除
3)将要发送的字符写入数据寄存器,这样发送器根据之前配置的UART模式将字符发送出去。
4. 在NVIC(Nested Vector Interrupt Controller)中使能UART2中断;
5. 进入for(;;)死循环,等待UART2接收中断产生。
UART2_IRTHandler程序:
void UART2_IRQHandler ()
(void)UART2->S1; /* Clear reception flag mechanism*/
Uart_Callback(Uart_GetChar());
1. 首先读取UART2 状态寄存器1来清除接收标志;
2. 调用Uart_GetChar()函数读取接收到的字符
1)等待UART2状态寄存器1中的RDRF(Receive Data Register Full Flag)置1;(个人觉得这一步可以省略,因为配置UART的时候我们只使能了Receiver Interrupt Enable for RDRF,省略之后编 译下载调试通过,收发OK,不过放在这里也没有错,通用性更好一些。)
2)读取UART2 状态寄存器1来清除RDRF标志(To clear RDRF, read UART_S1 with RDRF set and then read the UART data register(UART_D)),所以只有读取数据寄存器后RDRF才会清除;
3)从UART2数据寄存器读取接收到的字符。
UINT8 Uart_GetChar()
UINT8 recieve;
while(( UART2->S1 & UART_S1_RDRF_MASK)==0); /* Wait for received buffer to be full*/
(void) UART2->S1; /* Read UART2_S1 register*/
recieve= UART2->D; /* Read received data*/
return recieve;
实现:
下图是KEA64通过USB连接PC之后在设备管理器多出了两个:1. PEMicro OpenSDA Debug Driver用来OpenSDA 调试和下载用的,2.就是我们之前将过的USB Communication Device Classe(CDC),也就是USB转UART
下图是通过串口助手实现echo的功能:在发送窗口发送Freescale KEA MCU,在接收窗口立马接收到Freescale KEA MCU。实验成功
总结:UART是嵌入式开发中入门级别但是非常实用的一个模块,可以打印相关信息进行调试,也可以通过PC下发命令给我们的嵌入式系统进行相关控制。KEA-64的UART是具有LIN(Local Interconnect Network)功能的,只是在这个Lab1没有实现而已。Freescale的code写得非常不错,模块化设计思想很明显,注释也非常到位,基本上对照注释就能看懂代码,当然需要同时参照Reference Manual去熟悉寄存器的操作。这个Lab1中所有的代码都是直接操作寄存器的,性能很优,不过需要用户花时间去阅读Reference Manuanl。不知道Freescale有没有相关的平台化代码可以参考,即将底层的寄存器封装起来给用户直接用,用户不需要太关心底层的具体实现细节。个人感觉平台化设计是以后的一个趋势,就是通用的东西MCU原厂都封装好了,用户关注的是自己的功能。这里又不得不提一下mbed了呵呵,mbed就是这样干的。当然了个人想法而已,不一定对,大家共同探讨。