找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3031|回复: 9
收起左侧

实现按键次数在数码管上显示并通过串口发送到PC端

[复制链接]
ID:669905 发表于 2019-12-21 16:56 | 显示全部楼层 |阅读模式
下面的代码只实现了按键次数在数码管上显示,但是无论我怎么试,也没有办法把数码管的数据发送至串口助手,求大佬指点。
#include<reg52.h>
#include<stdlib.h>
#define uint unsigned long
#define uchar unsigned char

sbit led1 = P2^0;
sbit led2 = P2^1;
sbit led3 = P2^2;
sbit led4 = P2^3;

sbit k1 = P3^5;
sbit k2 = P3^4;
sbit k3 = P3^3;
sbit k4 = P3^2;
uchar code table[]={0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90};

uint num;

void delay(unsigned int i)
{
       
        while(i--);
  
  
}
void delayms(unsigned int i)
{
for(i=124;i>0;i--);  //Ñóê±124*8+10=1002us
}


void display(unsigned long num)
{
       
                led1=0;               
                P0=table[(num%10000)/1000];       
                delayms(1);               
                P0=0XFF;               
                led1=1;               

                led2=0;               
                P0=table[(num%1000)/100];       
                delayms(1);               
                P0=0XFF;               
                led2=1;

                led3=0;               
                P0=table[(num%100)/10];       
                delayms(1);               
                P0=0XFF;               
                led3=1;

                led4=0;               
                P0=table[num%10];       
                delayms(1);               
                P0=0XFF;               
                led4=1;
               
}



void main()
       
{
       
       



        num=0;       

        while(1)
        {
       
                SBUF=num;
                       
                display(num);
                       
                       
                if(k1==0)
                {
                       
                       
                        delayms(50);
                        if(k1==0)
                        {
                               
                                num++;
                        }
                       
                        while(!k1);
                        delayms(50);
                        while(!k1);
                               
                }
                       
        }
       
}

回复

使用道具 举报

ID:617449 发表于 2019-12-22 09:07 | 显示全部楼层
你好!
1、缺少串口初始化程序
2、缺少串口发送程序
3、增加上述程序后再试
回复

使用道具 举报

ID:638320 发表于 2019-12-22 10:27 | 显示全部楼层
要用一个发送标志位TI来判断,让它发送完成才执行下面的程序,即SBFU=number;
while(!TI);等待发送完成
TI=0;清标志位
回复

使用道具 举报

ID:213173 发表于 2019-12-22 11:35 | 显示全部楼层
要开定时器1做波特率发生器,按键后才发送,发送语句要完整。
  1. #include<reg52.h>
  2. #include<stdlib.h>
  3. #define uint unsigned long
  4. #define uchar unsigned char

  5. sbit led1 = P2^0;
  6. sbit led2 = P2^1;
  7. sbit led3 = P2^2;
  8. sbit led4 = P2^3;

  9. sbit k1 = P3^5;
  10. sbit k2 = P3^4;
  11. sbit k3 = P3^3;
  12. sbit k4 = P3^2;
  13. uchar code table[]={0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90};

  14. uchar key;

  15. void delayms(unsigned int i)
  16. {
  17.         unsigned int j;
  18.         while(i--)
  19.         {
  20.                 for(j=124;j>0;j--);
  21.         }
  22. }

  23. void display(uchar num)
  24. {       
  25.         led1=0;               
  26.         P0=table[(num%10000)/1000];        
  27.         delayms(1);               
  28.         P0=0XFF;
  29.         led1=1;               
  30.        
  31.         led2=0;               
  32.         P0=table[(num%1000)/100];        
  33.         delayms(1);               
  34.         P0=0XFF;               
  35.         led2=1;
  36.        
  37.         led3=0;               
  38.         P0=table[(num%100)/10];        
  39.         delayms(1);               
  40.         P0=0XFF;               
  41.         led3=1;
  42.        
  43.         led4=0;               
  44.         P0=table[num%10];        
  45.         delayms(1);               
  46.         P0=0XFF;               
  47.         led4=1;       
  48. }
  49. void main()        
  50. {//初始化定时器(波特率9600)
  51.         TMOD=0x20;
  52.         TH1=0xfd;
  53.         TH1=0xfd;
  54.         TR1=1;
  55.         REN=1;
  56.         SM0=0;
  57.         SM1=1;
  58. //初始键值
  59.         key=0;        
  60.         while(1)
  61.         {
  62.                 if(k1==0)
  63.                 {
  64.                         delayms(10);
  65.                         if(k1==0)
  66.                         {
  67.                                 if(key<255)
  68.                                         key++;
  69.                         }
  70.                         while(!k1);//等待松手
  71.                         SBUF=key;//键值发送到串口
  72.                         while(!TI);//等待发送完成
  73.                         TI=0;//清标志位
  74.                 }
  75.                 display(key);
  76.         }
  77. }
复制代码
回复

使用道具 举报

ID:164602 发表于 2019-12-22 15:53 | 显示全部楼层
wulin 发表于 2019-12-22 11:35
要开定时器1做波特率发生器,按键后才发送,发送语句要完整。

wulin:看看我这个程序,后面有记录。我解决不了。(用的是HC6800-ES-V2.0的板子)

#include<reg51.h>

#define GPIO_DIG P0//数码管显示口

sbit LSA=P2^2;//138译码器
sbit LSB=P2^3;
sbit LSC=P2^4;

sbit k1=P3^1;//按键1

unsigned char code DIG_CODE[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,
0x77,0x7c,0x39,0x5e,0x79,0x71};//数码管显示编码
unsigned char DD[2]={0x3f,0x00};//数码管显示缓存
unsigned char D0,D1;//串口发送缓存

void Delay10ms(unsigned int c)
{
    unsigned char a,b;
    for(c;c>0;c--)
        for(b=38;b>0;b--)
            for(a=130;a>0;a--);
}

void UsartConfiguration()//设置串口
{
        SCON=0X50;//串口通信设置为工作方式1
        TMOD=0X20;//设置定时器1工作方式2
        PCON=0X80;//波特率加倍
        TH1=0XF3;//计数器初始值设置,注意波特率是4800的
        TL1=0XF3;
        TR1=1;//打开计数器
}

void DigDisplay()//数码管显示函数
{
        unsigned char i;
        unsigned char j;
        for(i=0;i<2;i++)//只有2个数码管
        {
                switch(i)         //位选,选择点亮的数码管,
                {
                        case(0):
                                LSA=0;LSB=0;LSC=0; break;//显示第0位
                        case(1):
                                LSA=1;LSB=0;LSC=0; break;//显示第1位
                }
                GPIO_DIG=DD;//发送段码
                j=10;                                                 //扫描间隔时间设定
                while(j--);       
                GPIO_DIG=0x00;//消隐
        }
}

void CKFS (void)//串口发送
{
        SBUF = D1;
        while (!TI);
        TI = 0;
        SBUF = D0;
        while (!TI);
        TI = 0;
        SBUF = ' ';
        while (!TI);
        TI = 0;
}

void main(void)
{
        unsigned char i,j;//i为松手消抖计数变量;j为按键计数;
        UsartConfiguration();
        while(1)
        {       
                if(k1==0)//扫描键盘k1
                {
                        Delay10ms(1);//按下消抖
                        if(k1==0)
                        {
                                j++;
                                if (j>99)
                                {
                                        j=0;
                                }
                                if (j<10)
                                {
                                        DD[0]=DIG_CODE[j];
                                        DD[1]=0x00;
                                        D0 = (0x30+j);
                                        D1 = 0x00;
                                }
                                else
                                {
                                        DD[1]=DIG_CODE[j/10];
                                        DD[0]=DIG_CODE[j%10];
                                        D0 = (0x30+(j%10));
                                        D1 = (0x30+(j/10));
                                }
                            while((i<50)&&(k1==0))//松键消抖
                            {
                                    Delay10ms(1);
                                    i++;
                            }
                            i=0;
                        }
                        CKFS();
                }
                DigDisplay();
        }               
}


/*
编后感:
此程序是通过数码管显示按键次数(99以内),并且将次数通过串口发送到电脑。
但串口接收常常有乱码!
通过调试,发现这样的现象:
第一:单独的数码管显示没有问题;单独的串口发送也没有问题;
第二:个人感觉,两功能组合后,接收出现问题,主要是按键的消抖延时,影响到了串口工作的时序,
比如:串口发送的语句单独出现在按键程序中,串口根本接收不到有效数据,把它们集中到子函数中,
就可以接收到有效数据了。
第三:乱码问题没有根本解决,有部分数据没有乱码。根本原因没有找到,就无法解决。
*/


回复

使用道具 举报

ID:213173 发表于 2019-12-22 23:39 | 显示全部楼层
HC6800-ES-V2.0 发表于 2019-12-22 15:53
wulin:看看我这个程序,后面有记录。我解决不了。(用的是HC6800-ES-V2.0的板子)

#include

在此例程序中,按键与串口共用P3.1口,按键松手不稳,簧片抖动是产生乱码的主要原因。在有些开发板由于功能交叉会产生这样难题。写个程序解决一下学习问题无所谓。在实际应用电路中绝不可如此设计。给你把程序修改了一下,你试试。
  1. #include<reg51.h>

  2. #define GPIO_DIG P0//数码管显示口

  3. sbit LSA=P2^2;//138译码器
  4. sbit LSB=P2^3;
  5. sbit LSC=P2^4;

  6. sbit k1=P3^1;//按键1

  7. unsigned char code DIG_CODE[16]={//数码管显示编码
  8. 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
  9. 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
  10. unsigned char DD[]="00\n";//串口发送缓存
  11. //unsigned char D0,D1;//串口发送缓存
  12. unsigned char key=0;                //键值
  13. bit mark=0;//允许发送标志
  14. void Delayms(unsigned int c)
  15. {
  16.         unsigned int a;
  17.         for(c;c>0;c--)
  18.                 for(a=130;a>0;a--);
  19. }

  20. void UsartConfiguration()//设置串口
  21. {
  22.         SCON=0X50;//串口通信设置为工作方式1
  23.         TMOD=0X20;//设置定时器1工作方式2
  24.         PCON=0X80;//波特率加倍
  25.         TH1=0XF3;//计数器初始值设置,注意波特率是4800的
  26.         TL1=0XF3;
  27.         TR1=0;//关计数器
  28. }

  29. void DigDisplay()//数码管显示函数
  30. {
  31.         static bit i=0;
  32.         static unsigned int j=0;
  33.         if(++j>=100)
  34.         {
  35.                 j=0;
  36.                 GPIO_DIG=0x00;//消隐
  37.                 if(i){LSA=0;LSB=0;LSC=0;GPIO_DIG=DIG_CODE[key/10];}//显示十位       
  38.                 else {LSA=1;LSB=0;LSC=0;GPIO_DIG=DIG_CODE[key%10];}//显示个位
  39.                 i=~i;
  40.         }
  41. }
  42. void SendOneByte(unsigned char c)
  43. {
  44.     SBUF = c;                //发送数据
  45.     while(!TI);        //等待发送完成
  46.     TI = 0;                        //发送中断请求标志位清0
  47. }
  48. void CKFS()//串口发送
  49. {
  50.         static unsigned int i=0,j;
  51.         if(mark==1)
  52.         {
  53.                 if(++i>=1000)//计数延时
  54.                 {
  55.                         TR1=1;//开T1
  56.                         i=200;
  57.                     while(i--);//小延时
  58.                         for(j=0;j<3;j++)//发送两个字符+换行符
  59.                                 SendOneByte(DD[j]);
  60.                         TR1=0;//关T1
  61.                         mark=0;//允许发送标志清0
  62.                 }
  63.         }
  64. }

  65. void main(void)
  66. {
  67.         unsigned char count=0;        //消抖计数
  68.         bit flag=0;                                        //按键标志
  69.         UsartConfiguration();
  70.         Delayms(100);
  71.         while(1)
  72.         {        
  73.                 if(k1==0)//扫描键盘k1
  74.                 {
  75.                         if(++count>=100 && flag==0)
  76.                         {
  77.                                 flag=1;
  78.                                 key++;
  79.                                 if(key>99)
  80.                                         key=0;
  81.                                 if(key<10)
  82.                                 {
  83.                                         DD[0]=' ';
  84.                                         DD[1]=key%10+'0';
  85.                                 }
  86.                                 else
  87.                                 {
  88.                                         DD[0]=key/10+'0';
  89.                                         DD[1]=key%10+'0';
  90.                                 }
  91.                         }
  92.                 }
  93.                 else
  94.                 {
  95.                         if(flag)
  96.                         {
  97.                                 flag=0;
  98.                                 mark=1;//允许发送
  99.                         }
  100.                         count=0;
  101.                 }
  102.                 CKFS();
  103.                 DigDisplay();
  104.         }               
  105. }
复制代码
回复

使用道具 举报

ID:164602 发表于 2019-12-23 08:39 | 显示全部楼层
wulin 发表于 2019-12-22 23:39
在此例程序中,按键与串口共用P3.1口,按键松手不稳,簧片抖动是产生乱码的主要原因。在有些开发板由于功 ...

非常感谢你。程序已经验证。你的编程方法,也给我很大的提示!!!!!
是你指出了问题的根源,所以,我更改了按键,用k4键,占用P33口,就不冲突了,一切正常。
再次谢谢!
回复

使用道具 举报

ID:670959 发表于 2019-12-23 09:45 | 显示全部楼层
wulin:看看我这个程序,后面有记录。我解决不了。(用的是HC6800-ES-V2.0的板子)

#include<reg51.h>

#define GPIO_DIG P0//数码管显示口

sbit LSA=P2^2;//138译码器
sbit LSB=P2^3;
sbit LSC=P2^4;

sbit k1=P3^1;//按键1

unsigned char code DIG_CODE[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,
0x77,0x7c,0x39,0x5e,0x79,0x71};//数码管显示编码
unsigned char DD[2]={0x3f,0x00};//数码管显示缓存
unsigned char D0,D1;//串口发送缓存

void Delay10ms(unsigned int c)
{
    unsigned char a,b;
    for(c;c>0;c--)
        for(b=38;b>0;b--)
            for(a=130;a>0;a--);
}

void UsartConfiguration()//设置串口
{
        SCON=0X50;//串口通信设置为工作方式1
        TMOD=0X20;//设置定时器1工作方式2
        PCON=0X80;//波特率加倍
        TH1=0XF3;//计数器初始值设置,注意波特率是4800的
        TL1=0XF3;
        TR1=1;//打开计数器
}

void DigDisplay()//数码管显示函数
{
        unsigned char i;
        unsigned char j;
        for(i=0;i<2;i++)//只有2个数码管
        {
                switch(i)         //位选,选择点亮的数码管,
                {
                        case(0):
                                LSA=0;LSB=0;LSC=0; break;//显示第0位
                        case(1):
                                LSA=1;LSB=0;LSC=0; break;//显示第1位
                }
                GPIO_DIG=DD;//发送段码
                j=10;                                                 //扫描间隔时间设定
                while(j--);        
                GPIO_DIG=0x00;//消隐
        }
}

void CKFS (void)//串口发送
{
        SBUF = D1;
        while (!TI);
        TI = 0;
        SBUF = D0;
        while (!TI);
        TI = 0;
        SBUF = ' ';
        while (!TI);
        TI = 0;
}

void main(void)
{
        unsigned char i,j;//i为松手消抖计数变量;j为按键计数;
        UsartConfiguration();
        while(1)
        {        
                if(k1==0)//扫描键盘k1
                {
                        Delay10ms(1);//按下消抖
                        if(k1==0)
                        {
                                j++;
                                if (j>99)
                                {
                                        j=0;
                                }
                                if (j<10)
                                {
                                        DD[0]=DIG_CODE[j];
                                        DD[1]=0x00;
                                        D0 = (0x30+j);
                                        D1 = 0x00;
                                }
                                else
                                {
                                        DD[1]=DIG_CODE[j/10];
                                        DD[0]=DIG_CODE[j%10];
                                        D0 = (0x30+(j%10));
                                        D1 = (0x30+(j/10));
                                }
                            while((i<50)&&(k1==0))//松键消抖
                            {
                                    Delay10ms(1);
                                    i++;
                            }
                            i=0;
                        }
                        CKFS();
                }
                DigDisplay();
        }               
}


/*
编后感:
此程序是通过数码管显示按键次数(99以内),并且将次数通过串口发送到电脑。
但串口接收常常有乱码!
通过调试,发现这样的现象:
第一:单独的数码管显示没有问题;单独的串口发送也没有问题;
第二:个人感觉,两功能组合后,接收出现问题,主要是按键的消抖延时,影响到了串口工作的时序,
比如:串口发送的语句单独出现在按键程序中,串口根本接收不到有效数据,把它们集中到子函数中,
就可以接收到有效数据了。
第三:乱码问题没有根本解决,有部分数据没有乱码。根本原因没有找到,就无法解决。
*/
回复

使用道具 举报

ID:669905 发表于 2019-12-28 10:18 | 显示全部楼层
wulin 发表于 2019-12-22 11:35
要开定时器1做波特率发生器,按键后才发送,发送语句要完整。

你好,我试了您给的代码,但是在串口助手不是1234 这样的按键次数,而是81 82 83 84 85 86 87 80 81 8A 83 84 8D 8E 8F 90 91 82 83 8C 85 86 97 88 89 8A 8F 8C 8D这样的数
回复

使用道具 举报

ID:213173 发表于 2019-12-28 16:48 | 显示全部楼层
tomorrow101 发表于 2019-12-28 10:18
你好,我试了您给的代码,但是在串口助手不是1234 这样的按键次数,而是81 82 83 84 85 86 87 80 81 8A 8 ...

可能是你的串口助手没有调好。
无标题.jpg

回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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