找回密码
 立即注册

QQ登录

只需一步,快速开始

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

基于MODBUS协议的单片机主程序 测试通过

  [复制链接]
楼主
ID:929006 发表于 2021-7-25 13:55 | 显示全部楼层
大锅,拷贝你得程序,LCD根本不显示
回复

使用道具 举报

沙发
ID:929006 发表于 2021-7-25 20:37 | 显示全部楼层
为么我的程序,LCD不显示
#include"reg51.h"
#include"address.h"
#include"intrins.h"
#include"crc.h"

#define LCD1602_DB  P0
sbit LCD1602_RS = P1^0;
sbit LCD1602_RW = P1^1;
sbit LCD1602_E  = P1^5;

void InitLcd1602();
void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);

#define uint unsigned int
#define uchar unsigned char

uchar code sendbuf[]={0x01,0x03,0x02,0x00,0x00,0x03,0x04,0x73};          
//0x01 从站地址,0x03功能码,0x20寄存器地址高位,0x00寄存器地址低位,0x00数据个数高位,0x03数据个数低位,0x04CRC校验码高位,0x73CRC校验码低位
uchar code tab[]={'0','1','2','3','4','5','6','7','8','9'};
uchar code error[]={"error!"};
uchar tem[5],tem1[8];
uchar resvbuf[10];
int i,j;
uchar resvend,temp2;
uint crctemp,temp,temp1;


void convert10(uint dat)
{
  uchar i;
  tem1[0]='U';
  tem1[1]='=';
  tem1[7]='V';
  tem[0]=dat/10000;
  dat=dat%10000;
  tem[1]=dat/1000;
  dat=dat%1000;
  tem[2]=dat/100;
  dat=dat%100;
  tem[3]=dat/10;
  tem[4]=dat%10;
  for (i=0;i<5;i++)
  {
    tem1[i+2]=tab[tem[i]];
  }
}

void serial_int() interrupt 4         using 1
{
if(RI)
{
   RI=0;
   //temp2=SBUF;
    resvbuf[j++]=SBUF;  
   if(j==7)
   {
     j=0;
         resvend=1;
   }   
}       
}            

void initserial        ()
{
resvend=0;
TMOD=0x20;
PCON=0x00;
SCON=0xd8;
TL1=0xfd;
TH1=0xfd;
TR1=1;
ES=1;
}

void displayout()
{
   crctemp=crccheck(resvbuf,9);
   temp=resvbuf[9];
   temp=temp << 8 | resvbuf[10];
   if(temp==crctemp)
   {
        temp1=0;
            temp1 |=resvbuf[3];
                temp1= temp1<<8 | resvbuf[4];
                convert10(temp1);
                LcdShowStr(0, 1, tem1);
                //printf(tem1,8);
    }
  else
   {
                LcdShowStr(0, 1,error );
      //printf(error,16);
   }
}          

void delay_10us(uchar n)
{
   do
   {
     _nop_();
     _nop_();
     _nop_();
     _nop_();
     _nop_();
   }while(--n);
}

void delay_ms(uint n)
{
  do
  {
    delay_10us(131);
   }while(--n);
}

/* 等待液晶准备好 */
void LcdWaitReady()
{
    unsigned char sta;
   
    LCD1602_DB = 0xFF;
    LCD1602_RS = 0;
    LCD1602_RW = 1;
    do {
        LCD1602_E = 1;
        sta = LCD1602_DB; //读取状态字
        LCD1602_E = 0;
    } while (sta & 0x80); //bit7等于1表示液晶正忙,重复检测直到其等于0为止
}
/* 向LCD1602液晶写入一字节命令,cmd-待写入命令值 */
void LcdWriteCmd(unsigned char cmd)
{
    LcdWaitReady();
    LCD1602_RS = 0;
    LCD1602_RW = 0;
    LCD1602_DB = cmd;
    LCD1602_E  = 1;
    LCD1602_E  = 0;
}
/* 向LCD1602液晶写入一字节数据,dat-待写入数据值 */
void LcdWriteDat(unsigned char dat)
{
    LcdWaitReady();
    LCD1602_RS = 1;
    LCD1602_RW = 0;
    LCD1602_DB = dat;
    LCD1602_E  = 1;
    LCD1602_E  = 0;
}
/* 设置显示RAM起始地址,亦即光标位置,(x,y)-对应屏幕上的字符坐标 */
void LcdSetCursor(unsigned char x, unsigned char y)
{
    unsigned char addr;
   
    if (y == 0)  //由输入的屏幕坐标计算显示RAM的地址
        addr = 0x00 + x;  //第一行字符地址从0x00起始
    else
        addr = 0x40 + x;  //第二行字符地址从0x40起始
    LcdWriteCmd(addr | 0x80);  //设置RAM地址
}
/* 在液晶上显示字符串,(x,y)-对应屏幕上的起始坐标,str-字符串指针 */
void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str)
{
    LcdSetCursor(x, y);   //设置起始地址
    while (*str != '\0')  //连续写入字符串数据,直到检测到结束符
    {
        LcdWriteDat(*str++);  //先取str指向的数据,然后str自加1
    }
}
/* 初始化1602液晶 */
void InitLcd1602()
{
    LcdWriteCmd(0x38);  //16*2显示,5*7点阵,8位数据接口
    LcdWriteCmd(0x0C);  //显示器开,光标关闭
    LcdWriteCmd(0x06);  //文字不动,地址自动+1
    LcdWriteCmd(0x01);  //清屏
}


void main()
{
InitLcd1602();
initserial();
EA=1;
while(1)
{
  i=0;
  while(i<8)
  {
   SBUF=sendbuf[i];
   while(!TI);
   delay_10us(50);
   TI=0;
   i++;
  }
delay_ms(1000);
if(resvend)
  {
    resvend=0;
        displayout();
  }          
       

  }       
}  
回复

使用道具 举报

板凳
ID:929006 发表于 2021-7-26 12:30 | 显示全部楼层
上面程序有点错误,改了一下。还是不显示
#include"reg51.h"
#include"intrins.h"
#include"crc.h"

#define LCD1602_DB  P0
sbit LCD1602_RS = P1^0;
sbit LCD1602_RW = P1^1;
sbit LCD1602_E  = P1^5;

void InitLcd1602();
void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);

#define uint unsigned int
#define uchar unsigned char

uchar code sendbuf[]={0x01,0x03,0x02,0x00,0x00,0x03,0x04,0x73};          
//0x01 从站地址,0x03功能码,0x20寄存器地址高位,0x00寄存器地址低位,0x00数据个数高位,0x03数据个数低位,0x04CRC校验码高位,0x73CRC校验码低位
uchar code tab[]={'0','1','2','3','4','5','6','7','8','9'};
uchar code error[]={"error!"};
uchar tem[5],tem1[9];
uchar resvbuf[11];
int i,j;
uchar resvend,temp2;
uint crctemp,temp,temp1;


void convert10(uint dat)
{
  uchar i;
  tem1[0]='U';
  tem1[1]='=';
  tem1[7]='V';
  tem1[8]='\0';
  tem[0]=dat/10000;
  dat=dat%10000;
  tem[1]=dat/1000;
  dat=dat%1000;
  tem[2]=dat/100;
  dat=dat%100;
  tem[3]=dat/10;
  tem[4]=dat%10;
  for (i=0;i<5;i++)
  {
    tem1[i+2]=tab[tem[i]];
  }
}

void serial_int() interrupt 4         using 1
{
if(RI)
{
   RI=0;
   //temp2=SBUF;
    resvbuf[j++]=SBUF;  
   if(j==11)
   {
     j=0;
         resvend=1;
   }   
}       
}            

void initserial        ()
{
resvend=0;
TMOD=0x20;
PCON=0x00;
SCON=0xd8;
TL1=0xfd;
TH1=0xfd;
TR1=1;
ES=1;
}

void displayout()
{
   crctemp=crccheck(resvbuf,9);
   temp=resvbuf[9];
   temp=temp << 8 | resvbuf[10];
   if(temp==crctemp)
   {
        temp1=0;
            temp1 |=resvbuf[3];
                temp1= temp1<<8 | resvbuf[4];
                convert10(temp1);
                LcdShowStr(0, 1, tem1);
                //printf(tem1,8);
    }
  else
   {
                LcdShowStr(0,1,error);
      //printf(error,16);
   }
}          

void delay_10us(uchar n)
{
   do
   {
     _nop_();
     _nop_();
     _nop_();
     _nop_();
     _nop_();
   }while(--n);
}

void delay_ms(uint n)
{
  do
  {
    delay_10us(131);
   }while(--n);
}

/* 等待液晶准备好 */
void LcdWaitReady()
{
    unsigned char sta;
   
    LCD1602_DB = 0xFF;
    LCD1602_RS = 0;
    LCD1602_RW = 1;
    do {
        LCD1602_E = 1;
        sta = LCD1602_DB; //读取状态字
        LCD1602_E = 0;
    } while (sta & 0x80); //bit7等于1表示液晶正忙,重复检测直到其等于0为止
}
/* 向LCD1602液晶写入一字节命令,cmd-待写入命令值 */
void LcdWriteCmd(unsigned char cmd)
{
    LcdWaitReady();
    LCD1602_RS = 0;
    LCD1602_RW = 0;
    LCD1602_DB = cmd;
    LCD1602_E  = 1;
    LCD1602_E  = 0;
}
/* 向LCD1602液晶写入一字节数据,dat-待写入数据值 */
void LcdWriteDat(unsigned char dat)
{
    LcdWaitReady();
    LCD1602_RS = 1;
    LCD1602_RW = 0;
    LCD1602_DB = dat;
    LCD1602_E  = 1;
    LCD1602_E  = 0;
}
/* 设置显示RAM起始地址,亦即光标位置,(x,y)-对应屏幕上的字符坐标 */
void LcdSetCursor(unsigned char x, unsigned char y)
{
    unsigned char addr;
   
    if (y == 0)  //由输入的屏幕坐标计算显示RAM的地址
        addr = 0x00 + x;  //第一行字符地址从0x00起始
    else
        addr = 0x40 + x;  //第二行字符地址从0x40起始
    LcdWriteCmd(addr | 0x80);  //设置RAM地址
}
/* 在液晶上显示字符串,(x,y)-对应屏幕上的起始坐标,str-字符串指针 */
void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str)
{
    LcdSetCursor(x, y);   //设置起始地址
    while (*str != '\0')  //连续写入字符串数据,直到检测到结束符
    {
        LcdWriteDat(*str++);  //先取str指向的数据,然后str自加1
    }
}
/* 初始化1602液晶 */
void InitLcd1602()
{
    LcdWriteCmd(0x38);  //16*2显示,5*7点阵,8位数据接口
    LcdWriteCmd(0x0C);  //显示器开,光标关闭
    LcdWriteCmd(0x06);  //文字不动,地址自动+1
    LcdWriteCmd(0x01);  //清屏
}


void main()
{
InitLcd1602();
initserial();
EA=1;
while(1)
{
  i=0;
  while(i<8)
  {
   SBUF=sendbuf[i];
   while(!TI);
   delay_10us(50);
   TI=0;
   i++;
  }
delay_ms(1000);
if(resvend)
  {
    resvend=0;
        displayout();
  }          
       

  }       
}  

回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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