最近一直在弄UART,书和资料都不知道看了多少遍了,真怀疑是自己记忆力不好,搞了那么久都从来没把程序运行正确过,今天终于成功了。虽然并不是所有的程序都是自己写的,但对这个UART总算有点明白了,看开发板送的那个程序,虽然弄懂了是怎么回事,但是有很多地方始终不能理解,想从上面改也是相当的有难度,所以一直再找一个简洁版的程序,让自己明白到底UART要设置那些寄存器才能正常通讯,我觉得这一点也是相当重要的,从简单到复杂,那些培训搞的那些程序虽然功能齐全,但不利于我们学习,太太太复杂了。想从上面改,关联性太大了,文件也比较多,对于我这种菜鸟来说,实在是····哎。
整个工程就两个函数,一个是启动函数2440init.s一个是主函数Main.c。2440init.s也并不是那种复杂的,就几个简单的操作,就是功能少了点,想在主函数里面弄个蜂鸣器都不行,不做事哪里出了问题,我揣测是启动函数的问题吧,但对于写LED灯亮灭是没有问题的,做点流水灯或者其他的是没什么问题的,其实想简单的弄清楚UART的通讯的话,用LED灯的亮灭就够了。
下面先看程序吧
/*启动文件440init.s*/
IMPORT Main
CODE32
AREA Init,CODE,READONLY
ENTRY
ldr r0, =0x53000000 ;关门狗
mov r1, #0x0
str r1, [r0] ;关闭关门狗
ldr sp, =1024*4 ;设置堆栈,由于main函数里调用了其他函数,所以一定要设置堆栈
bl Main
main_loop
b main_loop
END
/*************************************************************************************************************************************
************************************************************************************************************************************
实现功能:当从终端输入一个字符后,当开发板接收到数据之后LED1会亮,随后延时一会就灭。如果开发板发送数据,那么LED3就亮,延时一会灭。这就可以体现出UART和PC机之间是否进行通讯了
*************************************************************************************************************************************/
/*主函数文件Main.c */
#define ULCON0 (*(volatile unsigned *)0X50000000) //UART线控制寄存器
#define UCON0 (*(volatile unsigned *)0X50000004) //UART控制寄存器
#define UFCON0 (*(volatile unsigned *)0X50000008) //FIFO控制寄存器
#define UMCON0 (*(volatile unsigned *)0x5000000c) //UART 0 Modem control
#define UTRSTAT0 (*(volatile unsigned *)0X50000010) //UART状态寄存器
#define UBRDIV0 (*(volatile unsigned *)0X50000028) //波特率
#define UTXH0 (*(volatile unsigned *)0X50000020) //发送数据寄存器8位
#define URXH0 (*(volatile unsigned *)0X50000024) //接收数据寄存器8位
#define GPBCON (*(volatile unsigned *)0x56000010) //Port B control
#define GPBDAT (*(volatile unsigned *)0x56000014) //Port B data
#define GPBUP (*(volatile unsigned *)0x56000018) //Pull-up control B
#define GPHCON (*(volatile unsigned *)0x56000070) //Port H control
#define GPHUP (*(volatile unsigned *)0x56000078) //Pull-up control H
#define GPHDAT (*(volatile unsigned *)0x56000074) //Port H data
//void LED_run(void);
void PORT_init(void);
void delay(unsigned int dly)
{
unsigned int i;
for(;dly>0;dly--)
for (i = 0;i < 60000; i++);
}
/*串口的设置可以归为以下几点1、端口初始化 2、线路控制寄存器(设置帧格式) 3、控制寄存器(设置时钟和方式) 4、波特率分频寄存器(设置波特率) 5、FIFO控制寄存器 6、MODEM控制寄存器 对应着下面程序*/
int Main()
{
char buf;
PORT_init(); //端口初始化
ULCON0 &=0XFFFFFF00;
ULCON0 |=0X03; //1位起始位,8位数据位
UCON0 =0X0805; //串口时钟PCLK,查询方式
UBRDIV0 =0X1A; //波特率115200
UFCON0 = 0; //FIFO控制寄存器
UMCON0 = 0; //MODEM控制寄存器
GPBDAT=(1<<5)|(1<<6)|(1<<7)|(1<<8); //对LED灯进行全灭设置,便于观察
while(1)
{
if(UTRSTAT0 & 0x01) //接收是否完毕(缓存寄存器接收到有效数据) =1结束 ARM从PC机上接受数据
{ /*如果把这里的if语句改写成while,那么现象会完全不一样,他会一直接受到数据, 也就会一直发送数据,在终端上显示数据,只要不对其进行干涉,就会一直显示下去。但是为 什么会显示“d”,这个问题没搞清楚,难道是下载程序时输入的那个d吗?*/
buf=URXH0;
GPBDAT&=~(1<<5); //为什么用LED2和4不能用呢??
delay(1000);
GPBDAT|=(1<<5);
while(!(UTRSTAT0 & 0x04)); //是否允许发送 (发生器空)=1允许
UTXH0=buf;
GPBDAT&=~(1<<7);
delay(1000);
GPBDAT|=(1<<7);
}
}
return 0;
}
void PORT_init(void)
{
GPBCON= 0x15400; //引脚从0开始 (01)表示输出方式
GPBUP=0xFFFF; //1表示无上拉电阻
GPHCON= 0xa0; //1010 0000 第2和3位选择为特殊功能(10)
GPHUP= 0x0c; //有上拉电阻
}
/*void LED_run()
{
GPBCON= 0x15400;//引脚从0开始
GPBUP=0xFFFF; //1表示无上拉电阻
while(1)
{
GPBDAT&=~0x20;
delay(102);
GPBDAT&=~0x60;
delay(100);
GPBDAT&=~0xE0;
delay(102);
GPBDAT&=~0x1E0;
delay(102);
GPBDAT|=0x20;
delay(120);
GPBDAT|=0x60;
delay(100);
GPBDAT|=0xE0;
delay(100);
GPBDAT|=0x1E0;
delay(100);
}
}*/