您的位置 首页 资料

单片机IO口模仿UART串口通讯

为了让大家充分理解UART串口通信的原理,我们先把P3.0和P3.1当做IO口来进行模拟实际串口通信的过程,原理搞懂后,我们再使用寄存器配置实现串口通信过程。对于UART串口波特率,常用的值是

  为了让咱们充沛了解 UART 串口通讯的原理,咱们先把 P3.0 和 P3.1 作为 IO 口来进行模仿实践串口通讯的进程,原理搞懂后,咱们再运用寄存器装备完结串口通讯进程。

  关于 UART 串口波特率,常用的值是 300、600、1200、2400、4800、9600、14400、19200、28800、38400、57600、115200 等速率。IO 口模仿 UART 串行通讯程序是一个简略的演示程序,咱们运用串口调试帮手下发一个数据,数据加 1 后,再主动回来。

  串口调试帮手,这儿咱们直接运用 STC-ISP 软件自带的串口调试帮手,先把串口调试帮手的运用给咱们说一下,如图 11-6 所示。第一步要挑选串口帮手菜单,第二步挑选十六进制显现,第三步挑选十六进制发送,第四步挑选 COM 口,这个 COM 口要和自己电脑设备管理器里的那个 COM 口共同,波特率按咱们程序设定好的挑选,咱们程序中让一个数据位持续时间是 1/9600 秒,那这个当地挑选波特率便是选 9600,校验位选 N,数据位 8,间断位 1。

  图 11-6 串口调试帮手示意图

  串口调试帮手的本质便是使用电脑上的 UART 通讯接口,发送数据给咱们的单片机,也可以把咱们的单片机发送的数据接纳到这个调试帮手界面上。

  由于初度触摸通讯方面的技能,所以我把后边的 IO 模仿串口通讯程序进行一下解说,咱们可以边看我的解说边看程序,把底层原理先完全弄懂。

  变量界说部分就不用说了,直接看 main 主函数。首先是对通讯的波特率的设定,在这儿咱们装备的波特率是 9600,那么串口调试帮手也得是 9600。装备波特率的时分,咱们用的是守时器 T0 的形式 2。形式 2 中,不再是 TH0 代表高 8 位,TL0 代表低 8 位了,而只要TL0 在进行计数,当 TL0 溢出后,不仅仅会让 TF0 变 1,而且还会将 TH0 中的内容从头主动装到 TL0 中。这样有一个优点,便是咱们可以把想要的守时器初值提早存在 TH0 中,当 TL0溢出后,TH0 主动把初值就从头送入 TL0 了,全主动的,不需求程序中再给 TL0 从头赋值了,装备方法很简略,咱们可以自己看下程序而且核算一下初值。

  波特率设置好今后,翻开间断,然后等候接纳串口调试帮手下发的数据。接纳数据的时分,首先要进行低电平检测 while (PIN_RXD),若没有低电平则阐明没有数据,一旦检测到低电平,就进入发动接纳函数 StartRXD()。接纳函数最开端发动半个波特率周期,初学或许这儿不是很理解。咱们回头看一下咱们的图 11-2 里面的串口数据示意图,如果在数据位电平改变的时分去读取,由于时序上的差错以及信号安稳性的问题很简单读错数据,所以咱们期望在信号最安稳的时分去读数据。除了信号改变的那个沿的方位外,其它方位都很安稳,那么咱们现在就约定在信号中心方位去读取电平状况,这样可以确保咱们读的一定是正确的。

  一旦读到了开端信号,咱们就把当时状况设定成接纳状况,而且翻开守时器间断,第一次是半个周期进入间断后,对开端位进行二次判别一下,承认一下开端位是低电平,而不是一个搅扰信号。今后每经过 1/9600 秒进入一次间断,而且把这个引脚的状况读到 RxdBuf 里面。等候接纳完毕之后,咱们再把这个 RxdBuf 加 1,再经过 TXD 引脚发送出去,相同需求先发一位开端位,然后发 8 个数据位,再发完毕位,发送完毕后,程序运转到 while (PIN_RXD),等候第二轮信号接纳的开端。

  #include

  sbit PIN_RXD = P3^0; //接纳引脚界说

  sbit PIN_TXD = P3^1; //发送引脚界说

  bit RxdOrTxd = 0; //指示当时状况为接纳仍是发送

  bit RxdEnd = 0; //接纳完毕标志

  bit TxdEnd = 0; //发送完毕标志

  unsigned char RxdBuf = 0; //接纳缓冲器

  unsigned char TxdBuf = 0; //发送缓冲器

  void ConfigUART(unsigned int baud);

  void StartTXD(unsigned char dat);

  void StartRXD();

  void main(){

  EA = 1; //开总间断

  ConfigUART(9600);

  while (1){ //装备波特率为 9600

  while (PIN_RXD); //等候接纳引脚呈现低电平,即开端位

  StartRXD(); //发动接纳

  while (!RxdEnd); //等候接纳完结

  StartTXD(RxdBuf+1); //接纳到的数据+1 后,发送回去

  while (!TxdEnd); //等候发送完结

  }

  }

  /* 串口装备函数,baud-通讯波特率 */

  void ConfigUART(unsigned int baud){

  TMOD &= 0xF0; //清零 T0 的操控位

  TMOD |= 0x02; //装备 T0 为形式 2

  TH0 = 256 – (11059200/12)/baud; //核算 T0 重载值

  }

  /* 发动串行接纳 */

  void StartRXD(){

  TL0 = 256 – ((256-TH0)>>1); //接纳发动时的 T0 守时为半个波特率周期

  ET0 = 1; //使能 T0 间断

  TR0 = 1; //发动 T0

  RxdEnd = 0; //清零接纳完毕标志

  RxdOrTxd = 0; //设置当时状况为接纳

  }

  /* 发动串行发送,dat-待发送字节数据 */

  void StartTXD(unsigned char dat){

  TxdBuf = dat; //待发送数据保存到发送缓冲器

  TL0 = TH0; //T0 计数初值为重载值

  ET0 = 1; //使能 T0 间断

  TR0 = 1; //发动 T0

  PIN_TXD = 0; //发送开端位

  TxdEnd = 0; //清零发送完毕标志

  RxdOrTxd = 1; //设置当时状况为发送

  }

  /* T0 间断服务函数,处理串行发送和接纳 */

  void InterruptTimer0() interrupt 1{

  static unsigned char cnt = 0; //位接纳或发送计数

  if (RxdOrTxd){ //串行发送处理

  cnt++;

  if (cnt <= 8){ //低位在先顺次发送 8bit 数据位

  PIN_TXD = TxdBuf & 0x01;

  TxdBuf >>= 1;

  }else if (cnt == 9){ //发送间断位

  PIN_TXD = 1;

  }else{ //发送完毕

  cnt = 0; //复位 bit 计数器

  TR0 = 0; //封闭 T0

  TxdEnd = 1; //置发送完毕标志

  }

  }else{ //串行接纳处理

  if (cnt == 0){ //处理开端位

  if (!PIN_RXD){ //开端位为 0 时,清零接纳缓冲器,预备接纳数据位

  RxdBuf = 0;

  cnt++;

  }

  }else{ //开端位不为 0 时,间断接纳

  TR0 = 0; //封闭 T0

  }else if (cnt <= 8){ //处理 8 位数据位

  RxdBuf >>= 1; //低位在先,所以将之前接纳的位向右移

  //接纳脚为 1 时,缓冲器最高方位 1,

  //而为 0 时不处理即仍坚持移位后的 0

  if (PIN_RXD){

  RxdBuf |= 0x80;

  }

  cnt++;

  }else{ //间断位处理

  cnt = 0; //复位 bit 计数器

  TR0 = 0; //封闭 T0

  if (PIN_RXD){ //间断位为 1 时,方能以为数据有用

  RxdEnd = 1; //置接纳完毕标志

  }

  }

  }

  }

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/ziliao/219311.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部