|  | 
 
| Learn lumit Step 4 : 驱动你的串口 和寄存器打交道 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
 系统完成进入 C 语言环境的初始化工作之后,第一个可以用 C 来写的就是串口
 驱动。在 lumit 网站上提供的启动代码里面,串口驱动是用汇编写的( sysinit.s )。
 这里我倒是觉得只要是能够用 C 来完成的工作,都尽量用 .h .c 的代码来实现。
 一个是便于理解,一个是便于移植,这两样都很重要。
 
 串口的驱动在各种处理器上的实现都大同小异:大同体现在主要是初始化时候设置
 波特率、停止位、奇偶校验、数据位等参数,这个过程就和在 PC 上打开超级终端进行
 参数设置一样。另外一些设置也很重要,比如是否启用中断方式,包括收数据中断和发
 数据中断,不过这同时也就需要实现中断处理函数来处理串口中断。
 
 小异主要就是在不同处理器的 UART 相关寄存器都或多或少存在不同,每个寄存器
 设置的相关 BIT 位代表的含义也有所差异。这个只要认真对照处理器手册,直接到相关
 UART 章节部分去找一下就知道了。
 
 在附件中 UART 驱动文件 uart.c 中,有一段代码还是比较有意思的,这里单独挑
 出来,和大家分享一下。
 
 /* UART primitives */
 #define GET_STATUS(p)        (*(volatile unsigned  *)((p) + USTAT))
 #define RX_DATA(s)             ((s) & USRRxData)
 #define GET_CHAR(p)        (*(volatile unsigned  *)((p) + URXBUF))
 #define TX_READY(s)            ((s) & USRTxHoldEmpty)
 #define PUT_CHAR(p,c)          (*(unsigned  *)((p) + UTXBUF) = (unsigned )(c))
 
 int uart_putchar( unsigned int UART_BASE, char ch )
 {
 /* read tx ready flag, when =1 break */
 while ( TX_READY(GET_STATUS(UART_BASE))==0)
 ;
 
 PUT_CHAR(UART_BASE, ch);
 
 return ch;
 }
 
 int uart_getchar( unsigned int UART_BASE, char * ch )
 {
 /* read rx data flag, when =1 break */
 while ( (RX_DATA(GET_STATUS(UART_BASE)))==0 )
 ;
 
 *ch = GET_CHAR(UART_BASE);
 
 return *ch;
 }
 
 第一部分是用宏定义了一组 UART 原语操作,主要是如下这5个:
 
 GET_STATUS(p)        : 获得当前 UART 状态
 RX_DATA(s)             : 接收数据到达标志
 TX_READY(s)            : 发送数据就绪标志
 GET_CHAR(p)        : 从缓冲获得一个数据
 PUT_CHAR(p,c)          : 向缓冲发送一个数据
 
 通过这组原语,配合一定的串口数据收发逻辑,也就是先看标志位,标志位表示
 许可操作的时候,才能进行收发,否则就是忙等待。这里实现了两个最底层的驱动接口:
 
 int uart_putchar( unsigned int UART_BASE, char ch );
 
 int uart_getchar( unsigned int UART_BASE, char * ch );
 
 附件里面还实现了一个最简单的 uart 驱动的测试函数 uart_test ,它的功能就是
 从串口接收一个用户发送的字符,然后再发送回去,即带 echo 回显的 getchar() 。
 有了底层的 UART 驱动接口,在上层就可以实现其他更多的数据收发接口了。
 | 
 
×本帖子中包含更多资源您需要 登录 才可以下载或查看,没有账号?注册  |