ARM cortex a 之串口通信2
现在开始编程。
先写一个大的函数:
void main(void)
{
uart_init();
uart_putc('a'); //发送数据
//uart_getc(); //接收数据
}
然后分别写三个小的子函数
先在宏定义中声明各个寄存器的地址,然后我们开始使用它们。
#define GPA0CON 0xE0200000
#define UCON0 0xE2900004
#define ULCON0 0xE2900000
#define UMCON0 0xE290000C
#define UFCON0 0xE2900008
#define UBRDIV0 0xE2900028
#define UDIVSLOT0 0xE290002C
#define UTRSTAT0 0xE2900010
#define UTXH0 0xE2900020
#define URXH0 0xE2900024
//下面是串口初始化程序
void uart_init(void)
{
//首先先选择GPA0CON控制寄存器,这个寄存器的作用是把IO口设置为串口模式
//先把这个寄存器的bit0~bit7清除,再写入0x22,则Rx Tx就设置成功了。
(*(volatile unsigned int *)GPA0CON) &= ~(0xff<<0);
(*(volatile unsigned int *)GPA0CON) |= 0x00000022;
//然后就是根据上一章讲的,我们来设置ULCON:设置串口的数据位,校验位和停止位
//这个寄存器的[31:7] 没有功能,这里写0x3的意思是:
//[1:0] 为11表示八位数据位,[2] 为0表示一位停止位,[5:3] 为0表示不需要校验位,
//[6] 为0表示正常模式(若选择1则表示红外模式);
(*(volatile unsigned int *)ULCON0) = 0x3;
//然后我们再设置UCONn寄存器
//这个寄存器的[1:0] 为01,表示中断请求或者轮询方式,[3:2] 为01,表示中断请求或者轮询方式
//[10]设置0,选择PCLK为时钟来源。剩下很多与中断有关的位我们先不需要管,毕竟我们用串口来做实验,
//不需要中断,不断来回检查就行了。
(*(volatile unsigned int *)UCON0) = 0x5;
//我们不使用流控,所以直接让UMCON全都为0,禁止掉。
(*(volatile unsigned int *)UMCON0) =0;
//我们不使用FIFO模式,所以同样把它们都设置为0就可以了。
(*(volatile unsigned int *)UFCON0) =0;
//然后就要计算配置波特率了
//PCLK_PSYS通过时钟系统分析为66.7MHz
//DIV_VAL = (66700000/(115200*16)-1) = 35.18,余数0.18
(*(volatile unsigned int *)UBRDIV0) = 35;
//(rUDIVSLOT中的1的个数 = 16*0.18= 2.88 = 3
//然后查阅手册,得知为0x888
(*(volatile unsigned int *)UDIVSLOT0) = 0x0888;
}
初始化完成了,现在开始写发送程序。
void uart_putc(char c)
{
//与uart功能有关的状态寄存器,记录了发送数据是否完成
//这个寄存器的bit3~bit31都没有功能,
//第bit2是transmitter empty位,发送缓冲器里面没有可供发送的数据的时候置1,有的话置0
//bit1位是如果有数据进入缓冲区则硬件自动置0,如果进入的数据被发送了出去,硬件再自动置一
//FIFO就是在发送器里面存一大堆数据,所以对于FIFO模式下,检测每次发送的数据是否发送了只能用
//检测bit1的方法,对于不使用FIFO模式来说,一次只发送一帧数据,而且都存在发送器里面,因此
//检测bit2和bit1都可以使用。
//首先一直循环检测,直到置1的时候,才能发送第二帧数据。
//
//bit0表示的是接收区的置位状态
while (!((*(volatile unsigned int *)UTRSTAT0) & (1<<1)));
(*(volatile unsigned int *)UTXH0) = c;
}
//会写发送程序以后,接收程序就简单多了。
char uart_getc(void)
{
while (!((*(volatile unsigned int *)UTRSTAT0) & (1<<0)));
return (*(volatile unsigned int *)URXH0);
}