找回密码
 立即注册

QQ登录

只需一步,快速开始

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

为什么在单片机LCD1602上会出现70 程序哪里错出错了?

[复制链接]
跳转到指定楼层
楼主
为什么在LCD1602上会出现70,为什么 按键k3、k4调速,将速度等级在LCD1602显示?我这程序哪里错出错了?
#include <reg52.h>      //包含52头文件
#define uint unsigned int //宏定义uint代替unsigned int
#define uchar unsigned char //宏定义uchar代替unsigned char
#define out P2
sbit lcdrs=P0^5;//液晶的RS端接P2.4口
sbit lcdrw=P0^6;//液晶的RW端接P2.5
sbit lcden=P0^7;// 液晶的EN使能端接P2.6口
sbit KEY1=P3^1;     //按键声明 //正转
sbit KEY2=P3^4;     //按键声明 //反转
sbit LED=P0^4;
unsigned long beats=0;//转动总拍数
unsigned long angle=0; //需要转动的角度
uchar code forturn[]={0x01,0x03,0x02,0x06,0x04,0x0c,0x08,0x09};//正转拍
uchar code revtutn[]={0x09,0x08,0x0c,0x04,0x06,0x02,0x03,0x01};//反转拍
uchar flag=0;//按键标志位
uchar flagmotor=0;//正反转标记
uchar temp;//临时变量
uchar index;//拍数索引
uchar motorturn=0;//电机转动圈数
void T0_init();//定时器
void T1_init();
void EX_init();//外部中断来控制加速减速
void forone();//正转
void reone();//反转
void stop(); //停止
void grade();//占空比等级
void delayms (uint xms);
void keyscan();
void write_str(uchar *str);
void write_data(uchar dat);
void check_busy(void);
void lcd_init();
void write_cmd(char cmd);
void xianshi();
void uart_init();
void lap();
uchar keyflag;  
uchar count=0,Hi=0,x,dat;
uchar num[6];

void  main()                            //主函数
{         motorturn=1;
        angle=motorturn*360;
        beats=(angle*4096)/360;        
        T0_init();
        EX_init();
        T1_init();
        lcd_init();
        uart_init();
        write_cmd(0x80);
        write_str("speed:");
    while(1)
    {  keyscan();
    switch(keyflag)
          {   case 1:{TR0=1;flagmotor=1;LED=0;}break;
             case 2:{TR0=1;flagmotor=2;LED=1;}break;
             default:stop();break;
          }
          lap();
               
    }
}
/*************定时器T1初始化函数**************/
void T1_init()
{
    TMOD=TMOD|0x20;    //设置T1为方式2
    TH1=256-200;          //置T1高8位,备用初值
    TL1=256-200;          //置T1低8位,初值        
    TR1=1;                              //启动T1
    ET1=1;                //开T1中断
    EA=1;                      //开总中断
}
/**********T0中断服务程序*********/
void T1_int() interrupt 3  //10ms进入中断
{
    TH1=(65536-100)/256;//置T0高8位初值
    TL1=(65536-100)%256;//置T0低8位初值
    count++;        //累计进入中断次数,进入1次为10ms
  if(count>=200)   //count累计200次为1s
{  

     count=0;     //1s后count清0,重新累计下一次1s  
}
if(count<Hi)flagmotor=1;
else flagmotor=0;        
}
/********外部中断0和外部中断1的中断服务函数*********/
void EX_init()
{
        IT0=1;            //外中断0下降沿触发
        EX0=1;            //允许外中断0中断
        PX0=1;            //优先级设置,可选
        IT1=1;            //外中断1下降沿触发
        EX1=1;            //允许外中断1中断
        PX1=1;            //优先级设置,可选
        EA=1;            //总中断允许
}

/********外部中断0中断服务函数*********/
void EX_INT0()  interrupt 0
{     uchar x=0;
    TR0=1;
    x++;
   if(x==5)x=4;
   xianshi();
   grade();
           
}
/********外部中断1中断服务函数*********/
void EX_INT1()  interrupt 2
{    uchar x=4;
    TR0=1;
          x--;
        if(x<=0)x=0;
        grade();
         xianshi();        
}
void stop()
{  P1=P1&0xf0;
}
void keyscan()        //按键检测函数  基础代码
{
    KEY1=1;           // 输入先写"1"
    if (KEY1==0)
    {
        delayms(10);    //延时去抖
        if(KEY1==0)   //按键按下
        {
           keyflag=1; //设标志位
        }
        while(!KEY1); //松手检测
    }

          KEY1=2;           // 输入先写"1"
    if (KEY2==0)
    {
        delayms(10);    //延时去抖
        if(KEY2==0)   //按键按下
        {
          keyflag=2; //设标志位
       }
        while(!KEY2); //松手检测
    }

         
}

void forone()
{ beats--;
  temp=P1;
  temp=temp&0xf0;
  temp=temp|forturn[index];
  P1=temp;
  index++;
  if(index==0x08)index=0;
  if(beats==0)
  {          P1=P1&0XF0;
          TR0=0;
         flag=0;
         index=0;
         flagmotor=0;
         angle=motorturn*360;
         beats=(angle*4096)/360;
  }
}

void delayms (uint xms)     //毫秒函数定义
{
    uint i,j;
    for(i=0;i<xms;i++)
       for(j=0;j<120;j++);  
}
void T0_init()
{
    TMOD=TMOD|0x01;                      //设置T0为方式1
    TH0=(65536-5000)/256;//置T0高8位初值
    TL0=(65536-5000)%256;//置T0低8位初值        
    TR0=0;                              //启动T0
    ET0=1;                //开T0中断
    EA=1;                      //开总中断
}
void T0_int() interrupt 1  //10ms进入中断
{
    TH0=(65536-5000)/256;//置T0高8位初值
    TL0=(65536-5000)%256;//置T0低8位初值        
   if(flagmotor==1)
      forone();
  if(flagmotor==2)
      stop();
}
void grade()
{ switch(x)
{case 1:Hi=20;break;
  case 2:Hi=60;break;
  case 3:Hi=100;break;
  case 4:Hi=140;break;
}
}

/**********************检查忙标志函数************************/
void check_busy(void)
{
    uchar dt;
        out=0xff;
        do
        {
           lcden=0;
           lcdrs=0;
           lcdrw=1;
           lcden=1;
           dt=out;
        }while(dt&0x80);
        lcden=0;
}
/**************************1602显示****************************/
void write_cmd(char cmd)  //写指令函数
{
        check_busy();
        lcden=0;//再把EN拉低
        lcdrs=0;
        lcdrw=0;//先将RW拉低
        out=cmd;
        lcden=1;
        lcden=0;
}
void write_data(uchar dat) //写数据函数
{
        check_busy();
        lcden=0;//再把EN拉低
        lcdrs=1;
        lcdrw=0;//先将RW拉低
        out=dat;
        lcden=1;
        lcden=0;        
}
void write_str(uchar *str)//写字符串函数
{
        while(*str!='\0')
        {
                write_data(*str++);
                delayms(5);
        }
}
/***************************初始化******************************/
void lcd_init()//初始化1602
{
        write_cmd(0x38);//显示模式设置
        write_cmd(0x0c);//显示开关,光标没有闪烁
        write_cmd(0x06);//显示光标移动设置
        write_cmd(0x01);//清除屏幕
        delayms(1);
}
void xianshi()
{   write_cmd(0x80+0x06);
    num[5]=Hi/10;
    num[5]=Hi%10;
    write_data(0x37+num[5]);
    write_data(num[5]+0x30);      
}
/****************串口方式1初始化*************/
void uart_init()
{
           SCON=0x50;                       //串口方式1,TI和RI清零,允许接收;
        PCON=0x80;                             //波特率加倍 SMOD=1
        TMOD=TMOD|0x20;                //T1定时方式2
           TH1=0xf3;
        TL1=0xf3;                         //4800b/s 晶振12MHz
           TR1=1;                           //启动T1
        ES=1;
        EA=1;
}

/*************中断接收一个字节数据函数*********/
void uart_receive() interrupt 4
{         
         if(RI==1)
{
RI = 0;                 //清TI标志位
dat=SBUF;         //接收数据存入变量dat
      }
}
void lap()
{   switch(dat)
{   case 0x01:{TR0=1;flagmotor=1;LED=0;}break;
    case 0x02:{TR0=1;flagmotor=2;LED=1;}break;
    case 0x03:{ TR0=1;x++;if(x==5)x=4;grade();xianshi();}break;
    case 0x04:{ TR0=1;x--;if(x==0)x=0;grade();xianshi();}break;

}
}

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

使用道具 举报

沙发
ID:161164 发表于 2023-12-20 22:53 | 只看该作者
错在这里



回复

使用道具 举报

板凳
ID:1096616 发表于 2023-12-21 09:58 | 只看该作者

我不理解这里怎么错了,真是抱歉啊,我这菜鸟啥也不懂
回复

使用道具 举报

地板
ID:161164 发表于 2023-12-21 10:18 | 只看该作者
深层次 发表于 2023-12-21 09:58
我不理解这里怎么错了,真是抱歉啊,我这菜鸟啥也不懂

num[5]=HI/10;
这句是取数值十位,没问题

num[5]=HI%10;
这句是取数值个位,为什么要把取得的值放到存放十位的数组里?

write_data(0x37+num[5]);
为啥要加0x37?

write_data(num[5]+0x30);
这里加0x30是对的,为了把数值转换为ASCII,并在LCD1602上显示
但好想用错了数组
回复

使用道具 举报

5#
ID:69038 发表于 2023-12-21 10:44 | 只看该作者
深层次 发表于 2023-12-21 09:58
我不理解这里怎么错了,真是抱歉啊,我这菜鸟啥也不懂

void xianshi()
{   write_cmd(0x80+0x06);
    num[5]=Hi/10;  // 这2行赋值到同一个变量了?
    num[5]=Hi%10;//

    write_data(0x37+num[5]); //1602接收显示数据的是ASCii码,“0”的是0x30,“7”是0x37,当num[5]=0时,显示出来就是7了,改成0x30试试
    write_data(num[5]+0x30);      
}
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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