找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1554|回复: 8
打印 上一主题 下一主题
收起左侧

关于STC8G单片机串口1发送数据不全的问题

[复制链接]
跳转到指定楼层
楼主
①我用的是STC8G1K08单片机;
②目的:按下并松开按键(完成一次完整的按键动作)后,向电脑屏幕发送准备好的数组;
③数组:0x01~07 和 0x07~01 两个数组
④出现的问题:发送的数据不全,屏幕显示 01 06 05 04 03 02 01 ,测试数组1只有01显示 后面都没了;
请问一下大家这是啥问题呀?
单片机源程序如下:
  1. #include "STC8G.H"
  2. #include <intrins.h>

  3. typedef unsigned char u8;
  4. typedef unsigned int u16;

  5. u8 T1_Count;
  6. u8 xdata T1BUF[6];

  7. bit F_T1_OK;
  8. bit Key_Sta = 1;
  9. bit Key_Backup = 1;
  10. bit F_t1ms;

  11. sbit Light = P1^6;
  12. sbit Key_G = P3^4;                //G


  13. //测试数组1
  14. void Ce_Arry1(void)
  15. {
  16.         T1BUF[0] = 0x01;
  17.         T1BUF[1] = 0x02;
  18.         T1BUF[2] = 0x03;
  19.         T1BUF[3] = 0x04;
  20.         T1BUF[4] = 0x05;
  21.         T1BUF[5] = 0x06;
  22.         T1BUF[6] = 0x07;
  23. }
  24. //测试数组2
  25. void Ce_Arry2(void)
  26. {
  27.         T1BUF[0] = 0x07;
  28.         T1BUF[1] = 0x06;
  29.         T1BUF[2] = 0x05;
  30.         T1BUF[3] = 0x04;
  31.         T1BUF[4] = 0x03;
  32.         T1BUF[5] = 0x02;
  33.         T1BUF[6] = 0x01;
  34. }
  35. //IO口初始化
  36. void IO_Init(void)
  37. {
  38.         P1M0 |= 0x40;
  39.         P1M1 = 0;
  40.         P3M0 = 0x00;                //P3准双向口
  41.         P3M1 = 0x00;                //P3准双向口
  42. }

  43. //定时器0初始化函数
  44. void Timer0_Init(void)                //500微秒@6.000MHz
  45. {
  46.         AUXR |= 0x80;                //定时器时钟1T模式
  47.         TMOD &= 0xF0;                //设置定时器模式
  48.         TL0 = 0x48;                //设置定时初值
  49.         TH0 = 0xF4;                //设置定时初值
  50.         TF0 = 0;                //清除TF0标志
  51.         TR0 = 1;                //定时器0开始计时
  52.         
  53.         ET0 = 1;
  54.         PT0 = 0;
  55. }

  56. //串口1初始化函数
  57. void Uart1_Init(void)                //57600bps@6.000MHz
  58. {
  59.         SCON = 0x50;                        //8位数据,可变波特率
  60.         AUXR |= 0x40;                        //定时器1时钟为Fosc,即1T
  61.         AUXR &= 0xFE;                        //串口1选择定时器1为波特率发生器
  62.         TMOD &= 0x0F;                        //设定定时器1为16位自动重装方式
  63.         TL1 = 0xE6;                                //设定定时初值
  64.         TH1 = 0xFF;                                //设定定时初值
  65.         ET1 = 0;                                //禁止定时器1中断
  66.         TR1 = 1;                                //启动定时器1
  67.         
  68.         ES = 1;
  69.         PS = 0;                                       
  70. }
  71. //串口发送程序
  72. void S1OUT(void)
  73. {
  74.         if(F_T1_OK==0)                        //串口1中断空闲
  75.         {
  76.                 F_T1_OK = 1;                //串口1处于中断中
  77.                 SBUF = T1BUF[0];        //进入串口1中断
  78.         }
  79. }
  80. //按键消抖
  81. void Key_Con(void)
  82. {
  83.         static u8 keybuf = 0xFF;
  84.         
  85.         if(F_t1ms==1)                                        //每1ms扫描一次键盘
  86.         {
  87.                 F_t1ms = 0;
  88.                
  89.                 keybuf = keybuf<<1 | Key_G; //8ms消抖
  90.                 if(keybuf==0x00)
  91.                 {
  92.                         Key_Sta = 0;                        //按键处于按下状态
  93.                 }
  94.                 else if(keybuf==0xFF)
  95.                 {
  96.                         Key_Sta = 1;                        //按键处于松开状态
  97.                 }
  98.         }
  99. }

  100. //按键处理内容
  101. void Key_CL(void)
  102. {

  103.         if(Key_Sta != Key_Backup)                //
  104.         {
  105.                 if(Key_Backup==0)                        //按键完成 按下——松开
  106.                 {
  107.                         Light = ~Light;
  108.                         Ce_Arry1();                           //1-7
  109.                         S1OUT();
  110.                         Ce_Arry2();                                //7-1
  111.                         S1OUT();
  112.                 }
  113.         }
  114.         Key_Backup = Key_Sta;                        //备份按键状态
  115. }

  116. //定时器0中断
  117. void Timer0_Routine(void) interrupt 1
  118. {
  119.         static t_1ms;
  120.         
  121.         if(++t_1ms>=2)
  122.         {
  123.                 t_1ms = 0;
  124.                 F_t1ms = 1;                //1ms置位1次
  125.         }        
  126. }
  127. //串口1中断
  128. void Uart1_Routine(void) interrupt 4
  129. {
  130.         if(TI==1)
  131.         {
  132.                 TI = 0;
  133.                 if(F_T1_OK==1)
  134.                 {
  135.                         T1_Count++;
  136.                         if(T1_Count<=6)
  137.                         {
  138.                                 SBUF = T1BUF[T1_Count];
  139.                         }
  140.                         else if(T1_Count>6)                //数组逐一赋值结束
  141.                         {
  142.                                 T1_Count = 0;
  143.                                 F_T1_OK = 0;                        //串口1中断 完成发送
  144.                         }
  145.                 }        
  146.         }
  147. }

  148. //主程序
  149. void main(void)
  150. {
  151.         EA = 1;
  152.         IO_Init();
  153.         Timer0_Init();
  154.         Uart1_Init();
  155.         Light = 0;
  156.         while(1)
  157.         {
  158.                 Key_Con();
  159.                 Key_CL();
  160.         }
  161. }
复制代码

0.png (5.08 KB, 下载次数: 55)

数组不全

数组不全
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:861694 发表于 2023-8-30 11:48 | 只看该作者
我想要的效果是按下按键后,显示屏显示:01 02 03 04 05 06 07 07 06 05 04 03 02 01 ,但是现实效果却是01 06 05 04 03 02 01,而且开头的01还是测试数组1的 0x01,不知道哪里出错了。。。
回复

使用道具 举报

板凳
ID:123289 发表于 2023-8-30 13:48 | 只看该作者
逻辑时序混乱。
回复

使用道具 举报

地板
ID:883242 发表于 2023-8-30 14:30 | 只看该作者
问题出在118~121行,119行只发送了一个字节就进入下一行了。

评分

参与人数 1黑币 +10 收起 理由
戡拤 + 10 的确是此函数有问题

查看全部评分

回复

使用道具 举报

5#
ID:861694 发表于 2023-8-30 14:46 | 只看该作者
Hephaestus 发表于 2023-8-30 14:30
问题出在118~121行,119行只发送了一个字节就进入下一行了。

我的理解是S1OUT( );中,F_T1_OK=1,之后进入串口1发送中断,直到将测试数组1全部发完,如果不是这样考虑的话,请问该往哪个方向想?
回复

使用道具 举报

6#
ID:161164 发表于 2023-8-30 16:13 | 只看该作者
  1. //串口发送程序
  2. void S1OUT(void)
  3. {
  4.         if(F_T1_OK==0)                        //串口1中断空闲
  5.         {
  6.                 F_T1_OK = 1;                //串口1处于中断中
  7.                 SBUF = T1BUF[0];        //进入串口1中断
  8.         }
  9.                 while(F_T1_OK);
  10. }
复制代码


评分

参与人数 1黑币 +15 收起 理由
戡拤 + 15 万分感谢!

查看全部评分

回复

使用道具 举报

7#
ID:861694 发表于 2023-8-30 16:44 | 只看该作者

谢谢,这行while语句直接救命!我是这样理解这段代码的,SBUF = T1BUF[0]这行代码就是开启串口1发送中断-->TI = 1,既然进入了串口中断,不应该是把剩下的0x2-6逐一赋值给SBUF吗?可是现实执行效果是直接跳出了中断,执行了第二个S1OUT( ),请问可以告诉我哪里考虑有误吗?还有while(F_T1_OK)没有语句块,为啥可以跳出循环呀,可以解释一下吗吗?
回复

使用道具 举报

8#
ID:161164 发表于 2023-8-30 16:58 | 只看该作者
戡拤 发表于 2023-8-30 16:44
谢谢,这行while语句直接救命!我是这样理解这段代码的,SBUF = T1BUF[0]这行代码就是开启串口1发送中断- ...

SBUF = T1BUF[0]这行代码只是开始发送
离发送完毕,开启串口1发送中断-->TI = 1 还有一段时间
于是就继续往下运行Ce_Arry2();

while(F_T1_OK)没有语句块,但中断里154行有

评分

参与人数 1黑币 +15 收起 理由
戡拤 + 15 感谢解答!

查看全部评分

回复

使用道具 举报

9#
ID:861694 发表于 2023-8-30 17:22 | 只看该作者
lkc8210 发表于 2023-8-30 16:58
SBUF = T1BUF[0]这行代码只是开始发送
离发送完毕,开启串口1发送中断-->TI = 1 还有一段时间
于是就继 ...

竟然还有这中情况吗?给SBUF赋值完8位数据后,TI并不会马上置1是吗?while(F_T1_OK)就是限制程序将Ce_Arry1( );全部赋值给SBUF后,才执行Ce_Arry2( );吗?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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