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

    本实验要完成的内容是:通过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

//  声明函数
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里的方向指向串口就可以了。

你可能感兴趣的:(ARM,UART)