3042|6

25

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

单片机串口中断和定时中断同时使用的显示问题 [复制链接]

#include
#include
       
#define uchar  unsigned char
#define uint   unsigned int
sbit RS = P3^5 ;
sbit RW = P3^6 ;
sbit EN = P3^7 ;
sbit BUSY = P2^7;
sbit LED = P0^0;
sbit zhendong = P0^1;
sbit spk = P0^2;
sbit k1 = P0^3;
sbit k2 = P0^3;
sbit k3 = P0^5;
sbit k4 = P0^6;
uchar HMS_string[]="    00:00:00    ";
uchar buf,millisecond,hour = 0,minute = 0,second = 0;
uint m,n;
bit settime = 0;
bit change_H_or_M=1; // 1表示修改时,0表示修改分
uchar RX_BUF[20];  //串口接受到的数据缓冲区域
uchar flag_head=0;  //数据标志
uchar RX_data_ln=0;  //串口接收到的数据长度
uchar flag_rev=0;  //一次数据接受完成标志
/****************************************************************************
                           延迟程序
****************************************************************************/

void delay(uint h)
{
  for(m=0;m     for(n=0;n<110;n++) ;
}
/*********************************************************************
  LCD1602       
***********************************************************************/
/**
* 等待繁忙标志
*/

void wait(void)
{
        P2 = 0xFF;
        do
        {
                RS = 0;
                RW = 1;
                EN = 0;
                EN = 1;
        }while (BUSY == 1);
        EN = 0;
}

//写数据

void w_dat(uchar dat)
{
        wait();
        EN = 0;
        P2 = dat;
        RS = 1;
        RW = 0;
        EN = 1;
        EN = 0;
}

//写命令

void w_cmd(uchar cmd)
{
        wait();
        EN = 0;
        P2 = cmd;
        RS = 0;
        RW = 0;
        EN = 1;
        EN = 0;
}

/**
* 初始化1602
*/
void Init_LCD1602(void)
{
        w_cmd(0x38);  // 16*2显示,5*7点阵,8位数据接口
        w_cmd(0x0C);  // 显示器开、光标开、光标允许闪烁
        w_cmd(0x06);  // 文字不动,光标自动右移
        w_cmd(0x01);  // 清屏
}
/****************蜂鸣函数**************************************************/
void beep()
{
  uchar i,j=70;
  for(i=0;i<200;i++)
   {
    while(--j);
        spk = ~spk;
        }
   delay(300);
   spk = 0;
}
/*******显示函数,在LCD指定的行上显示字符串********************************/
void display_string(uchar *str,uchar lineNo)
{
  uchar k;
  for(k=0;k<16;k++)
   {
     w_cmd(lineNo+k);
         w_dat(str[k]);
   }
}
/***************时分秒显示**************************************/
void display_HMS(uchar h,m,s)
{
  if(settime)
    HMS_string[3] = '>';
  else
    HMS_string[3] = ' ';
  HMS_string[4] = h/10 +'0';
  HMS_string[5] = h%10 +'0';
  HMS_string[7] = m/10 +'0';
  HMS_string[8] = m%10 +'0';
  HMS_string[10] = s/10 +'0';
  HMS_string[11] = s%10 +'0';
  display_string(HMS_string,0xC0);
}
/******************设置时间*******************************/
void change_time()
{
  settime = 0;

// if(k1==0||k2==0||k3==0)
//  {
  //   TR0 = 0;
//         settime = 1;
  // }
  while(settime)
   {
     if(k1==0)
          {
            beep();
            while(k1==0)
                change_H_or_M = !change_H_or_M;
           }
            else if(k2==0)
           {
             beep();
                 while(k2==0);
                  if(change_H_or_M==1)
                   {if(++hour==24)  hour = 0;}
                     else
                  {if(++minute==60) minute = 0;}
            }
             else if(k3==0)
            {
                  beep();
                  while(k3==0);
                  if(change_H_or_M==1)
                    {if(--hour==0xff) hour=23;}
                  else
                     {if(--minute==0xff) minute=59;}
                 }
           else if(k4==0)
             {
                   beep();
                   while(k4==0);
                   settime = 0;
                   TR0 = 1;
                 }
                display_HMS(hour,minute,second);
   }
}
/********************************************************************
                              主函数
*******************************************************************/

void main(void)
{       
    uint i;
    TMOD=0x21;           //定时器1工作于8位自动重载模式, 用于产生波特率
    SCON=0x50;           //设定串口工作方式
    PCON=0x00;           //波特率不倍增               
    TH1 = 256-(22118400/12/16/115200);
    TL1 = TH1;
        TH0 = 0x4c;
        TL0 = 0x00;
        IP = 0x10;

        TR0 = 1;
        ET0 = 1;
        TR1 = 1;
    ET1 = 1;
        spk = 0;
        ES = 1;              //允许串口中断       
        EA=1;
        Init_LCD1602();
        while(1)
     {
       if(flag_rev==1)   //判断数据接受完成
         {
                   flag_rev=0;                  
                   if(RX_BUF[2]>='1'&&RX_BUF[3]!='.')
                         {
                           LED = 0;
               delay(100);
               LED = ~LED;
               delay(100);
               zhendong = 0;
              }     
               else
            {zhendong = 1;}
                  }
    for(i=1;i            {
             w_cmd(0x80+i-1);
         w_dat(RX_BUF[1+i]);
         delay(100);
            }      
        display_HMS(hour,minute,second);
        delay(100);
        change_time();
      }
}
/*************************************************************
               串行中断服务函数
*************************************************************/

void  serial() interrupt 4
{
if(RI ==1)
   {
      //ES = 0;                //关闭串行中断
      RI = 0;                //清除串行接受标志位
      buf = SBUF;            //从串口缓冲区取得数据
    if(buf=='R'&&flag_head==0)  //表明接收到了数据头
      {
         RX_data_ln=0;
         flag_head=1;
         return;
       }
   if(buf=='\r'&&flag_head==1)//接受到了数据尾
         {
                  flag_rev=1;   //接受完成标志
          flag_head=0;  
          return;
         }
     if(flag_head==1)
         {
             RX_BUF[++RX_data_ln]=buf;
                    
     }
    //ES = 1;    //允许串口中断       
           }
else
   {
     TI=0;
    }
}
/************************************************************/
void timer0() interrupt 1
{
  TH0 = 0x4c;
  TL0 = 0x00;
  if(++millisecond == 39)
  {
    millisecond = 0;
        if(++second==59)
         {
           second = 0;
           if(++minute ==59)
             {
                  minute = 0;
                  if(++hour==23)
                   {
                           hour = 0;
                        minute = 0;
                        second = 0;
                    }
                  }
          }
  }
}

程序结果显示如图
LCD上面一行本来应该显示串口接受的数据,下面一行显示时间。但是现在串口接受的数据显示不出来了,怎么才能使上面的接受数据显示出来?(备注:在加时间程序前,串口程序时刻以接受数据并且是能够显示的。)




IMG_20150606_124436.jpg (739.51 KB, 下载次数: 0)

IMG_20150606_124436.jpg
此帖出自51单片机论坛

最新回复

LCD1602内部RAM显示缓冲区地址的映射图,00~0F、40~4F分别对应LCD1602的上下两行的每一个字符,只要往对应的RAM地址写入要显示字符的ASCII代码,就可以显示出来。 显示单个字符子程序: void display_lcd_byte(uchar y,uchar x,uchar z)    //Y=0,1(起始行)X=0~15(起始列)Z=想写字符的ASCII码 {              if(y)      //是否显示在第二行(若在第一行Y=0,不进入IF语句,若在第二行,进入IF语句   {            x+=0x40;   //第二行起始地址加上列数为字符显示地址   }   x+=0x80;      //设置数据指针位置 } 然后就可以显示了  详情 回复 发表于 2015-6-17 16:35
点赞 关注
 

回复
举报

1万

帖子

25

TA的资源

版主

沙发
 
看上去你的代码有问题:

  for(i=1;i            {
             w_cmd(0x80+i-1);
         w_dat(RX_BUF[1+i]);
         delay(100);
            }      

直接用void display_string(uchar *str,uchar lineNo)函数试试。
此帖出自51单片机论坛

点评

我把RX_data_ln改成16的话 ,上面的一行就显示,但是是乱码.  详情 回复 发表于 2015-6-6 19:16
用display_string函数之后上面一行是乱码。麻烦能解释一下那段程序的主要问题吗?谢谢了。  详情 回复 发表于 2015-6-6 18:15
 
 
 

回复

25

帖子

0

TA的资源

一粒金砂(中级)

板凳
 
dcexpert 发表于 2015-6-6 17:43
看上去你的代码有问题:

  for(i=1;i

用display_string函数之后上面一行是乱码。麻烦能解释一下那段程序的主要问题吗?谢谢了。
此帖出自51单片机论坛

点评

你在for循环中没有正确调用显示的程序,你仔细看看就明白。 你是怎样调用display_string的?  详情 回复 发表于 2015-6-6 21:35
 
 
 

回复

25

帖子

0

TA的资源

一粒金砂(中级)

4
 
dcexpert 发表于 2015-6-6 17:43
看上去你的代码有问题:

  for(i=1;i

我把RX_data_ln改成16的话 ,上面的一行就显示,但是是乱码.
此帖出自51单片机论坛
 
 
 

回复

1万

帖子

25

TA的资源

版主

5
 
30419089 发表于 2015-6-6 18:15
用display_string函数之后上面一行是乱码。麻烦能解释一下那段程序的主要问题吗?谢谢了。

你在for循环中没有正确调用显示的程序,你仔细看看就明白。
你是怎样调用display_string的?
此帖出自51单片机论坛
 
 
 

回复

164

帖子

0

TA的资源

一粒金砂(中级)

6
 
应该是中断打断了显示,可以在显示的时候关闭中断。
此帖出自51单片机论坛
 
个人签名专业电子方案/zigbee方案设计,毕业设计。QQ:1397905781
 
 

回复

1234

帖子

4

TA的资源

纯净的硅(高级)

7
 
LCD1602内部RAM显示缓冲区地址的映射图,00~0F、40~4F分别对应LCD1602的上下两行的每一个字符,只要往对应的RAM地址写入要显示字符的ASCII代码,就可以显示出来。
显示单个字符子程序:
void display_lcd_byte(uchar y,uchar x,uchar z)    //Y=0,1(起始行)X=0~15(起始列)Z=想写字符的ASCII码
{         
    if(y)      //是否显示在第二行(若在第一行Y=0,不进入IF语句,若在第二行,进入IF语句
  {        
   x+=0x40;   //第二行起始地址加上列数为字符显示地址
  }
  x+=0x80;      //设置数据指针位置
}
然后就可以显示了
此帖出自51单片机论坛
 
个人签名天地庄周马;江湖范蠡船。
个性签名还是放QQ号吧,2060347305,添加说明EEworld好友
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表