标签:
嵌入式系统实验通用异步收发器uartmini2440armj-linkkeil-uvisio |
分类: 实验报告 |
实验五:通用异步收发器(UART)实验
一、实验目的
1、掌握 UART 外设的操作原理和编程。
2、学习使用 UART 进行多机通讯。
二、实验设备
1、硬件:PC 机一台 、Mini2440 ARM 实验板一套 J-link 仿真器一套
2、软件:WindowsXP 系统,Keil uVision 4.0 集成开发环境
三、实验内容
(1)使用 C 语言编写 UART 基本收发数据程序,进行 2 个实验板之间的数据收发测试。
(2)用两个实验板模拟嵌入式控制系统中的数据采集/控制实验,其中一个实验板模拟数据采集模块,将通过 UART 返回数据;另一块实验板模拟控制系统的主机,通过 UART 采集数据,并通过 UART 发出控制指令。
四、实验预习要求
(1)学习 UART 相关的原理概念;
(2)查阅 S3C2440 芯片手册,了解 UART0 结构和原理。
五、实验步骤
(1)启动 Keil uVision,新建一个工程ex05。不需要系统提供的 Startup 文件。建立汇编源文件 ex05.s,编写实验程序,然后添加到工程中。设置工程选项,存储器映射。设置工程调试选项。建立仿真初始化文件 RAM.ini。
(2)建立 C 语言源文件 main.c,编写实验程序,然后添加到工程中。
(3)使用交叉串口电缆连接两个实验板。
(4)编译程序, 使用仿真器在目标板上调试运行程序, 使用单步、 设置断点,观察程序执行时,收发数据的值。
六、实验程序
C 语言实验程序见程序清单 5。
程序清单 4.1 UART 实验程序
// Uart0
#define WrUTXH0(ch) (*(volatile unsigned char *)0x50000020)=(unsigned char)(ch)
#define RdURXH0()
#define rULCON0
#define rUCON0
#define rUFCON0
#define rUMCON0
#define rUTRSTAT0
#define rUERSTAT0
#define rUFSTAT0
#define rUMSTAT0
#define rUBRDIV0
#define rGPHCON
#define rGPHUP
//PCLK:12MHz
#define PCLK 12000000
//( (int)(pclk/16./baud+0.5) -1 )
#define baud_value 12
void Uart_Init()
{
Mode, Receive Mode
01
Interrupt or Polling
rGPHCON |= 0xaa;//use GPH port as uart0
}
void Uart_SendByte(int data)
{
char Uart_Getch(void)
{
}
main()
{
Uart_Init();
Uart_SendByte(c);
七、实验现象
两块实验板在接收指令处设断点,然后实验板1全速运行,实验板2接着全速运行,实验板1自动暂停。此时实验板1接收到‘b’的ASIC码(之前储存的是‘a’),实验板2现在储存的是‘c’。
八、思考题
(1)UART 的 FIFO 对改进通讯性能和可靠性有什么作用?
答:FIFO对通讯性能的改进:在进行UART通信时,中断方式比轮询方式要简便且效率高。但是,如果没有收发FIFO,则每传输一个数据(5~8位)都要中断处理一次,效率仍然不高。如果有了收发FIFO,则可以在连续收发若干个数据后才产生一次中断,然后一起处理。这就大大提高了收发效率。
FIFO对可靠性的作用:如果没有接收超时功能,则在对方已经发送完毕而接收FIFO未填满时并不会触发中断(FIFO满才会触发中断),结果造成最后接收的有效数据得不到处理的问题。有了接收超时功能后,如果接收FIFO未填满而对方发送已经停,则在不超过3个字的数据的接收时间内就会触发超时中断,因此数据会照常得到处理。
(2)两个实验板互连通讯,波特率设置满足什么关系时可以正确通讯?
答:当两个实验板用UART进行通讯时,如果打算使接受的第N位数据为正确位时,需要满足下式:
http://s7/middle/7bf0c30f4a66bcae533c6&690
当字长度为8位数据位时,如果要确保数据接收正确,那么波特率误差必须在5%以内。例如:标准波特率为9600,那么ARM允许的波特率范围为9120—10080。
所以当两个实验板通讯时,每次发送N位数据(包括起始位、数据位、停止位、奇偶校验位等),两个实验板的波特率误差应该满足:
http://s15/middle/7bf0c30f4a66bcaf219be&690
九、选做题
(1) 使用一个实验板上的按键控制另一个实验板上的LED 指示灯状态。
两个实验板之间进行通讯需要用到UART,其中一个作为发送端,另一个作为接收端。
作为发送端的实验板需要增加代码用来处理按键,先设置GPIO,然后不停的读取按键的状态,写入到UART中,然后UART发送出去。
作为接收端的实验班需要增加爱代码用来处理指示灯,设置好GPIO之后,不停的从UART中读取数据,然后写入到控制灯的GPIO中去。
两个实验板UART的设置诸如波特率要相同,实验板1的按键状态每发生一次该变,实验板2的指示灯的状态也发生一次改变。
UART实际发送的数据可以不是按键装态,只需要发送一个能够反应实验板1的按键状态的值即可。约定当实验板1的按键状态发生变化时,通过UART向实验板2发送字符‘1’,否则发送字符‘0’;接收端收到字符‘1’时,就改变指示灯的状态,否则不改变。
最终的实验程序如下所示:
#define rGPBCON (*(volatile unsigned *)0x56000010 //Port B control register指示灯
#define rGPBDAT (*(volatile unsigned *)0x56000014 //Port B data register
#define rGPGCON (*(volatile unsigned *)0x56000060 //Port G control register按键
#define rGPGDAT (*(volatile unsigned *)0x56000064 //Port G data register
#define WrUTXH0(ch) (*(volatile unsigned char *)0x50000020)=(unsigned char)(ch)
#define RdURXH0() (*(volatile unsigned char *)0x50000024)
#define rULCON0 (*(volatile unsigned *)0x50000000) //UART 0 Line control
#define rUCON0 (*(volatile unsigned *)0x50000004) //UART 0 Control
#define rUFCON0 (*(volatile unsigned *)0x50000008) //UART 0 FIFO control
#define rUMCON0 (*(volatile unsigned *)0x5000000c) //UART 0 Modem control
#define rUTRSTAT0 (*(volatile unsigned *)0x50000010) //UART 0 Tx/Rx status
#define rUERSTAT0 (*(volatile unsigned *)0x50000014) //UART 0 Rx error status
#define rUFSTAT0 (*(volatile unsigned *)0x50000018) //UART 0 FIFO status
#define rUMSTAT0 (*(volatile unsigned *)0x5000001c) //UART 0 Modem status
#define rUBRDIV0 (*(volatile unsigned *)0x50000028) //UART 0 Baud rate divisor
#define rGPHCON (*(volatile unsigned *)0x56000070) //Port H control
#define rGPHUP (*(volatile unsigned *)0x56000078) //Pull-up control H
#define PCLK 12000000//PCLK:12MHz
#define baud_value 12 //( (int)(pclk/16./baud+0.5) -1 ),57600
void Uart_Init()
{
int i;
rUFCON0 = 0x0; //UART channel 0 FIFO control register, FIFO disable
rUMCON0 = 0x0; //UART chaneel 0 MODEM control register, AFC disable
rULCON0 = 0x3; //Line control register : Normal,No parity,1 stop,8 bits
// [10] [9] [8] [7] [6] [5] [4] [3:2] [1:0]
// Clock Sel, Tx Int, Rx Int, Rx Time Out, Rx err, Loop-back, Send break, Transmit
Mode, Receive Mode
// 0 1 0 , 0 1 0 0 ,
01 01
// PCLK Level Pulse Disable Generate Normal Normal
Interrupt or Polling
rUCON0 = 0x245; // Control register
rUBRDIV0= baud_value; //Baud rate divisior register 0
for(i=0;i<100;i++)
;
rGPHCON |= 0xaa;//use GPH port as uart0
rGPHUP =0x0f;//the pull up function is disabled
}
void Uart_SendByte(int data)
{
WrUTXH0(data);
}
char Uart_Getch(void)
{
while(!(rUTRSTAT0 & 0x1)); //Receive data ready
return RdURXH0();
}
实验板1的main函数(用于发送按键状态)
main()
{
int state=0x7fff;
Uart_Init();
rGPGCON= =0x15400;
rGPGDAT=0x7fff;
while(1)
{
if(state!=rGPGDAT)
{
state=rGPGDAT;
Uart_SendByte(‘1’);
}
else
Uart_SendByte(‘0’);
}
}
实验板2的main函数,用于接受实验板1的按键状态:
main()
{
Uart_Init();
rGPBCON= 0x15400;
while(1)
{
if(Uart_Getch()==’1’)
{
rGPBDAT=0x1e0;
}
else
rGPBDAT=0x00;
}
}