您的位置:首页 > 其它

ARM课程实验二 UART 串口通信实验

2012-10-12 21:10 288 查看
本实验要完成的内容是:通过UART接口将分秒位显示在PC机上,并且通过键盘设置分秒位。应该看到1234567890123...效果。

PA_9和PA_10分别作为输出和输入脚即TX1和RX1。如图是连接图:





主函数如下:

// 定义定时器寄存器地址

#define SysTick_CTRL (*(volatile unsigned long *) (0xE000E010))

#define SysTick_LOAD (*(volatile unsigned long *) (0xE000E014)) //就是STRVR

// 定义时钟允许寄存器地址

#define RCC_APB2ENR (*(volatile unsigned long *) (0x40021018))

// 定义GPIOA寄存器地址

#define GPIOA_CRH (*(volatile unsigned long *) (0x40010804))

// 定义USART1寄存器地址

#define USART1_BRR (*(volatile unsigned long *) (0x40013808))

#define USART1_CR1 (*(volatile unsigned long *) (0x4001380c))

#define USART1_SR (*(volatile unsigned long *) (0x40013800))

#define USART1_DR (*(volatile unsigned long *) (0x40013804))

#include <stdio.h>

// 声明函数

void SysTick_Init(void);

void SysTick_Handler(void);

void Usart1_Init(void);

void Txd_Sec(void);

void Rxd_Sec(void);

int Usart1_Txd(int data);

int Usart1_Rxd(void);

int fputc(int ch, FILE *f);

// 声明全局变量

int sec = 0, sec1 = 0,min=0,min1=0,num=0;

// 主函数

int main(void)

{

SysTick_Init(); // 初始化系统定时器

Usart1_Init(); // 初始化USART1

while(1)

{

SysTick_Handler(); // 定时处理

Txd_Sec();

Rxd_Sec(); //发送个位(一秒一次)

}

}

// 系统定时器初始化子程序

void SysTick_Init(void)

{

SysTick_LOAD = 1000000; // 1s定时值(时钟源频率为8MHz/8),每记一次数是1ms,故1,000,000次为1s

SysTick_CTRL = 1; // 启动定时器,SysTick_CTRL为控制寄存器

}

// 定时处理子程序

void SysTick_Handler(void)

{

if(SysTick_CTRL & 0x10000) //1s时间到,SysTick_CTRL的16位为计数标志位,当systick计到0时,该位被置1,

{

if((++sec & 0xf) >= 0xa) sec += 6; // 2-10 进制调整

if(sec >= 0x60)

{sec = 0; // 60s 时间到,复位为0

if((++min & 0xf) >= 0xa) min += 6; // 2-10 进制调整

if(min >= 0x60) min = 0;

} // 60s 时间到,复位为0

}

}

// UART1 初始化子程序

void Usart1_Init(void)

{

RCC_APB2ENR |= 0x4004; // 开启USART1 和GPIOA 时钟 ,2位与14位分别是端口A和USART1的时钟使能位

GPIOA_CRH &= 0xffffff0f;

GPIOA_CRH |= 0x000000b0; // PA.09(TX1)复用推挽输出、仅对PA.09操作,未对PA.10操作,它是默认状态,PA.10(RX1)浮空输入

//GPIOA_CRH ^= 0x000000f0; // 复位状态下效果和以上2 条语句相同

USART1_BRR = 0x0045; // 8000000/115200=69(0x45) 设置波特率为115200

USART1_CR1 = 0x200C; // UART 允许、发送和接收允许,允许中断

//(8位数据、无校验、1 位停止)

}

// USART1 发送子程序

// 入口参数:data-发送数据

// 出口参数:返回发送数据

int Usart1_Txd(int data)

{

while(!(USART1_SR & 0x80)); // 等待TXE=1(发送数据寄存器TDR空,已经被转移到发送移位寄存器)

return(USART1_DR = data); // 发送并返回数据

}

// USART1 接收子程序

// 出口参数:接收数据(接收成功)/0(接收不成功)

int Usart1_Rxd(void)

{

if(USART1_SR & 0x20) // RXNE=1(接收数据寄存器RDR不空,数据已经收到)

return USART1_DR; // 返回接收数据

else

return 0; // 否则返回0

}

// USART 发送sec 个位子程序(1s 发送1 次)

void Txd_Sec(void)

{

if(sec != sec1) // 1s 时间到

{

sec1 = sec;

// Usart1_Txd((sec & 0x0f) + 0x30); // 发送sec 个位(转化为ASCII 码)

printf("%c%c%c%c%c",((min & 0xf0)/0x10) + 0x30 ,(min & 0x0f) + 0x30,0x3a,((sec & 0xf0)/0x10) + 0x30 ,(sec & 0x0f) + 0x30);

//if(!(sec&0xf)) // sec 个位为0

printf("%c", 0xd); // 发送回车

printf("%c", 0xa); // 发送换行

}

}

// USART 设置sec 个位子程序

void Rxd_Sec(void)

{ int data,d[4];

data= Usart1_Rxd();

if(data)

{d[num]=data;

num++;

data=0;

switch(num)

{

case 1:min = (min & 0x0f) + (d[0] - 0x30)*0x10;break;

case 2:min = (min & 0xf0) + (d[1] - 0x30); break;

case 3:sec = (sec & 0x0f) + (d[2] - 0x30)*0x10; break;

case 4:sec = (sec & 0xf0) + (d[3] - 0x30); break;

}

}

}

int fputc(int ch, FILE *f)

{

return(Usart1_Txd(ch)); //向usart写数据

}

这个跟程序比cc2430的那个相对简单,没有显示在lcd屏上,也少了删除的功能。注意不管是接受数据还是发送数据都是以ascII码的形式进行通信,所以当进行设置秒位时,除了输入数字进行设置,还可以输入其他字符,只不过会转成相应的ASCII码值。

UART数据寄存器DR是分成两个部分的,对外虽是一个,但是读、写是对不同的寄存器进行操作,包括TDR和RDR如图:



在显示秒位的时候还可以使用printf函数:

把Usart1_Txd((sec & 0x0f) + 0x30);Usart1_Txd(0xd); Usart1_Txd(0xa); 分别改成

printf("%c", (sec & 0x0f) + 0x30);printf("%c", 0xd); printf("%c", 0xa); 即可

由于printf定义在stdio.h里面,所以要加上这个头文件,还要加上这个fputc函数:

int fputc(int ch, FILE *f)

{

return(Usart1_Txd(ch));

}

因为printf函数默认的输出是显示器输出,如果要在串口或lcd输出必须重新定义相关的函数,比如printf要输出到串口,将fputc里的方向指向串口就可以了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: