登录  | 立即注册

游客您好!登录后享受更多精彩

扫一扫,访问微社区

QQ登录

只需一步,快速开始

开启左侧

[寒假笔记] UART串口通信的基本应用

[复制链接]
发表于 2018-2-3 23:17:52 | 显示全部楼层 |阅读模式
学习笔记
学习科目: 单片机基础
学习安排: 学会使用UART串口通信模块进行简单的串口通信
开始时间: 2018-02-03
结束时间:
前面学完了定时器和中断,而今天又接触到了串口通信。通信分为并行通信和穿行通信,今天学的是串行通信,串行通信顾名思义就是数据一个一个的传输,就像排成了一串。在单片机中有两个引脚专门用作UART通信,一个是P30一个是P31,它们组成的通信接口就叫做串行接口,简称串口。下面是两个单片机进行串口通信的示意图
串口通信.png
下面来着重讲一下单片机的UART模块,是专门用来进行串口通信的。下面来说一下怎么使用它
360截图189306196883111.png 这就是UART模块的串行控制寄存器-SCON。在这里我们只需要知道我们常使用模式1还有TI和RI的作用即可,
那么对SCON的配置就是SCON=0x50。 TI是发送中断标志位,当发送数据时由硬件置1,发送完毕后需要软件清零;RI是接收中断标志位,当接收数据时由硬件置1,接收完毕后需要软件清零。数据的传输和接收都需要涉及到波特率,波特率就是发送二进制数据的速率,只有当通信双方的波特率一样时才能保证通信的正常进行。我们可以选择定时器1作为波特率发生器(不能选定时器0),这就需要我们打开定时器1并且对其进行一系列的配置。
对于定时器1的TH0和TL0的重装值设定有一个计算公式:TH1=TL1=256-晶振/12/32/波特率。这波特率未倍速的情况,也可以利用PCON寄存器来让波特率倍速(PCON &=0x7f),由于部里的开发板上的晶振是32MHz 在计算过程中会出现除不尽的情况,这是可以写成:TH1=TL1=256-(unsigned int)(晶振/12/32/波特率+0.5)。但是仍然存在误差,所以我不建议使用定时器1来作为波特率发生器。这个时候就可以使用stc12c5a60s2单片机中的独立波特率发生器了,由于其不会由于晶振的缘故产生较大的误差而且使用起来也比较方便,所以我就使用了独特波特率发生器作为波特率发生器了,辅助寄存器AUXR中有相关的说明,这里及简而言之了若要使用就需要配置AUXR为:AUXR=0x15,这里是使用1T模式,除此之外还需要设置独立波特率发生器寄存器(BRT)的重装值,这里的计算我也不太清楚,但是在我们使用的isp下载其中有计算的地方,如下图所示:
360截图17571123765975.png 我们只需要设置好晶振和波特率就可以算出BRT的值了,还直接可以得到对寄存器的配置情况,可谓是非常方便了。
   当初在学习中断时,可以发现中断允许寄存器有一个ES寄存器,这就是本贴的最后一个内容了-串行口1中断允许位
我们可以将数据的发送和接收都放在UART中断中执行,这样便为主函数中腾出了位置好用来执行其他的指令。
下面是一个通过UART模块实现单片机和电脑通信的源代码:
#include<stc12c5a60s2.h>
sbit ENLED = P1^1;
void UartInit();
void ConfigTimer0(unsigned int ms);

unsigned char code LedChar[] = {
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
unsigned char LedBuff[] = {
0xff,0xff,0xff,0xff,0xff,0xff,0xff};

unsigned char T0RH = 0;
unsigned char T0RL = 0;
unsigned char RxdByte = 0;
void main ()
{
ENLED = 0;
UartInit();
ConfigTimer0(1);
EA = 1;
while(1)
{
  LedBuff[0] = LedChar[RxdByte&0x0f];
  LedBuff[1] = LedChar[RxdByte>>4];
}
}

/*串口配置函数*/
void UartInit()  //9600bps@32MHz
{
ES = 1;
PCON &= 0x7F; //波特率不倍速
SCON = 0x50;  
AUXR |= 0x04; //设置为1T模式
BRT = 0x98;   //设定独立波特率发生器重装值
AUXR |= 0x01; //串口1选择独立波特率发生器为波特率发生器
AUXR |= 0x10; //启动独特波特率发生器
}

void ConfigTimer0(unsigned int ms)
{
unsigned long tmp;
tmp = 32000000/1;
tmp = (tmp*ms)/1000;
tmp = 65536 - tmp;
tmp = tmp + 13;
T0RH = (unsigned char)(tmp>>4);
T0RL = (unsigned char)tmp;
AUXR |= 0x80;
TH0 = T0RH;
TL0 = T0RL;
ET0 = 1;
TR0 = 1;
}

void LedScan()
{
static unsigned char i = 0;
P0 = 0xff;
P2 = 0xfd-i;
P0 = LedBuff;
if(i<5)
  i++;
else
  i = 0;
}

void InterruptTimer0() interrupt 1
{
TH0 = T0RH;
TL0 = T0RL;
LedScan();
}
void InterruptUART() interrupt 4
{
if(RI)
{
  RI = 0;
RxdByte= SBUF;
  SBUF = RxdByte;
}
if(TI)
{
  TI = 0;
}
}




。。。
发表于 2018-2-4 09:16:18 | 显示全部楼层
波特率计算的方法还是了解一下为好~
该会员没有填写今日想说内容.
 楼主| 发表于 2018-2-4 23:24:49 | 显示全部楼层
alpha 发表于 2018-2-4 09:16
波特率计算的方法还是了解一下为好~

好的,知道了
。。。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表