📄 1602lcd-2.c
字号:
#include <REG51.H>
#include <INTRINS.H> //为调用nop空指令需要
#define DS_NOP() _nop_();_nop_();_nop_();_nop_()
#define REF_Voltage 5.25 //ADC0809基准电压
#define PLUS_CH0 1 //各个通道增益
#define PLUS_CH1 1
#define PLUS_CH2 1
#define PLUS_CH3 5
#define PLUS_CH4 1
#define PLUS_CH5 1
#define PLUS_CH6 1
#define PLUS_CH7 1
/**************ADC0809引脚定义**********/
sbit ST = P2^5;
sbit OE = P2^4;
sbit EOC = P2^3;
sbit ADC0809_C = P2^2;
sbit ADC0809_B = P2^1;
sbit ADC0809_A = P2^0;
/**************LCD引脚定义*************/
sbit LCM_RW = P3^6; //定义LCD引脚
sbit LCM_RS = P3^7;
sbit LCM_E = P3^5;
#define LCM_Data P1
#define Busy 0x80 //用于检测LCM状态字中的Busy标识
/************函数声明*******************/
void LCMInit(void);
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData);
void DisplayNumberFloat(unsigned char X, unsigned char Y,float Number,unsigned char point_number);
void Delay5Ms(void);
void Delay400Ms(void);
void Decode(unsigned char ScanCode);
void WriteDataLCM(unsigned char WDLCM);
void WriteCommandLCM(unsigned char WCLCM,BuysC);
unsigned char ReadDataLCM(void);
unsigned char ReadStatusLCM(void);
unsigned char code cdle_net[] = {" welcome... "};
unsigned char code email[] = {"VoltageTestDemo!"};
unsigned char code Cls[] = {" "};
float VoltageSurvey(unsigned char AD_ChannelNumber);
void main(void)
{
float CHa_voltage; //显示在第一行上的测量电压
float CHb_voltage; //显示在第二行上的测量电压
Delay400Ms(); //启动等待,等LCM讲入工作状态
LCMInit(); //LCM初始化
Delay400Ms();
DisplayListChar(0, 0, cdle_net);
DisplayListChar(0, 1, email);
Delay400Ms();
Delay400Ms();
Delay400Ms();
Delay400Ms();
WriteCommandLCM(0x01,1); //显示清屏,光标归位,地址归位
DisplayListChar(15, 0, "V"); //显示单位
DisplayListChar(15, 1, "V");
WriteCommandLCM(0x0c,1); //关光标,关闪烁
while(1)
{
CHa_voltage = VoltageSurvey(0); //测量通道0电压
DisplayListChar(0, 0, "CH0:");
DisplayNumberFloat(7,0,CHa_voltage,2); //在LCD中部显示通道0电压
Delay5Ms();
CHb_voltage = VoltageSurvey(1); //测量通道1电压
DisplayListChar(0, 1, "CH1:");
DisplayNumberFloat(7,1,CHb_voltage,2); //在LCD中部显示通道1电压
Delay5Ms();
Delay400Ms(); //延时1.6s,即停留显示1.6s
Delay400Ms();
Delay400Ms();
Delay400Ms();
CHa_voltage = VoltageSurvey(2);
DisplayListChar(0, 0, "CH2:");
DisplayNumberFloat(7,0,CHa_voltage,2);
Delay5Ms();
CHb_voltage = VoltageSurvey(3);
DisplayListChar(0, 1, "CH3:");
DisplayNumberFloat(7,1,CHb_voltage,2);
Delay5Ms();
Delay400Ms();
Delay400Ms();
Delay400Ms();
Delay400Ms();
CHa_voltage = VoltageSurvey(4);
DisplayListChar(0, 0, "CH4:");
DisplayNumberFloat(7,0,CHa_voltage,2);
Delay5Ms();
CHb_voltage = VoltageSurvey(5);
DisplayListChar(0, 1, "CH5:");
DisplayNumberFloat(7,1,CHb_voltage,2);
Delay5Ms();
Delay400Ms();
Delay400Ms();
Delay400Ms();
Delay400Ms();
CHa_voltage = VoltageSurvey(6);
DisplayListChar(0, 0, "CH6:");
DisplayNumberFloat(7,0,CHa_voltage,2);
Delay5Ms();
CHb_voltage = VoltageSurvey(7);
DisplayListChar(0, 1, "CH7:");
DisplayNumberFloat(7,1,CHb_voltage,2);
Delay5Ms();
Delay400Ms();
Delay400Ms();
Delay400Ms();
Delay400Ms();
}
}
/*
//#######################################################################################################################################
//#######################################################################################################################################
ADC0809驱动部分
*/
/*****************************************************
ADC0809转换函数
输入: 通道号(0-7)
返回: 测量到的模拟电压所对应的数字量
*****************************************************/
unsigned char ADC0809test(unsigned char ch0)
{
unsigned char ADCdata; //AD转换后得到的数字量
ST = 0;
EOC = 1;
OE = 0;
switch(ch0)
{
case 0:
{
ADC0809_A = 0;
ADC0809_B = 0;
ADC0809_C = 0;
break;
}
case 1:
{
ADC0809_A = 1;
ADC0809_B = 0;
ADC0809_C = 0;
break;
}
case 2:
{
ADC0809_A = 0;
ADC0809_B = 1;
ADC0809_C = 0;
break;
}
case 3:
{
ADC0809_A = 1;
ADC0809_B = 1;
ADC0809_C = 0;
break;
}
case 4:
{
ADC0809_A = 0;
ADC0809_B = 0;
ADC0809_C = 1;
break;
}
case 5:
{
ADC0809_A = 1;
ADC0809_B = 0;
ADC0809_C = 1;
break;
}
case 6:
{
ADC0809_A = 0;
ADC0809_B = 1;
ADC0809_C = 1;
break;
}
case 7:
{
ADC0809_A = 1;
ADC0809_B = 1;
ADC0809_C = 1;
break;
}
default:break;
}
ST = 1;
ST = 0;
DS_NOP();
while(EOC == 0)
{
;
}
if(EOC == 1)
{
OE = 1;
ADCdata = P0;
return (ADCdata);
}
}
/*******************************************************
电压测量并装换成实际的电压值
入口参数: AD_ChannelNumber 输入通道号:在0-7之间选择
出口参数: 转换后的电压值,实际的值
********************************************************/
float VoltageSurvey(unsigned char AD_ChannelNumber)
{
float SurveyVoltage; //测量到的电压值
float plus_ch; //通道增益
switch(AD_ChannelNumber)
{
case 0: plus_ch = PLUS_CH0;break;
case 1: plus_ch = PLUS_CH1;break;
case 2: plus_ch = PLUS_CH2;break;
case 3: plus_ch = PLUS_CH3;break;
case 4: plus_ch = PLUS_CH4;break;
case 5: plus_ch = PLUS_CH5;break;
case 6: plus_ch = PLUS_CH6;break;
case 7: plus_ch = PLUS_CH7;break;
default:break;
}
SurveyVoltage = ADC0809test(AD_ChannelNumber);
SurveyVoltage = (SurveyVoltage / 256) * REF_Voltage * plus_ch;
return(SurveyVoltage);
}
/*
//#######################################################################################################################################
//#######################################################################################################################################
LCD驱动部分
*/
//写数据
void WriteDataLCM(unsigned char WDLCM)
{
ReadStatusLCM(); //检测忙
LCM_Data = WDLCM;
LCM_RS = 1;
LCM_RW = 0;
LCM_E = 0; //若晶振速度太高可以在这后加小的延时
LCM_E = 0; //延时
LCM_E = 1;
}
//写指令
void WriteCommandLCM(unsigned char WCLCM,BuysC) //BuysC为0时忽略忙检测
{
if (BuysC) ReadStatusLCM(); //根据需要检测忙
LCM_Data = WCLCM;
LCM_RS = 0;
LCM_RW = 0;
LCM_E = 0;
LCM_E = 0;
LCM_E = 1;
}
//读数据
unsigned char ReadDataLCM(void)
{
LCM_RS = 1;
LCM_RW = 1;
LCM_E = 0;
LCM_E = 0;
LCM_E = 1;
return(LCM_Data);
}
//读状态
unsigned char ReadStatusLCM(void)
{
LCM_Data = 0xFF;
LCM_RS = 0;
LCM_RW = 1;
LCM_E = 0;
LCM_E = 0;
LCM_E = 1;
while (LCM_Data & Busy); //检测忙信号
return(LCM_Data);
}
void LCMInit(void) //LCM初始化
{
LCM_Data = 0;
WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号
Delay5Ms();
WriteCommandLCM(0x38,0);
Delay5Ms();
WriteCommandLCM(0x38,0);
Delay5Ms();
WriteCommandLCM(0x38,1); //显示模式设置,8位数据,2行显示,5*7点阵,开始要求每次检测忙信号
WriteCommandLCM(0x08,1); //关闭显示,关屏幕,关光标,关闪烁
WriteCommandLCM(0x01,1); //显示清屏,光标归位,地址归位
WriteCommandLCM(0x06,1); // 显示光标移动设置,每显示一个地址加1,不整体移位.
WriteCommandLCM(0x0c,1); // 显示开及光标设置,开屏幕,关光标,关闪烁.
}
//按指定位置显示一个字符
//送入该字符所对应的ASCII码
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
{
Y &= 0x1;
X &= 0xF; //限制X不能大于15,Y不能大于1
if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;
X |= 0x80; //算出指令码
WriteCommandLCM(X, 1); //发命令字
WriteDataLCM(DData); //发数据
}
//按指定位置显示一串字符
//由于*DData是字符型指针变量,所以在提取该指针变量所指向的字符时得到的就是该字符的ASCII码.
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)
{
unsigned char ListLength;
ListLength = 0;
Y &= 0x1;
X &= 0xF; //限制X不能大于15,Y不能大于1
while (DData[ListLength]>0x19) //若到达字串尾则退出
{
if (X <= 0xF) //X坐标应小于0xF
{
DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符
ListLength++;
X++;
}
}
}
/**********************************************************
在送入地址上显示一个浮点数.
输入:地址,浮点数,小数点位数.
函数设计允许最大不超过100的浮点数,小数位数选择:0,1,2
**********************************************************/
void DisplayNumberFloat(unsigned char X, unsigned char Y,float Number,unsigned char point_number)
{
unsigned char number_10bit; //用于暂存10位数据的变量
unsigned char number_1bit; //用于暂存个位数据的变量
unsigned char number_point_1; //用于保存第一位小数
unsigned char number_point_2; //用于保存第二位小数
unsigned int int_number; //用于将输入的浮点型数字转换为整形
if((Number < 100) && (point_number <= 2))
{
Y &= 0x1;
X &= 0xF; //限制X不能大于15,Y不能大于1
if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;
X |= 0x80; //算出指令码
WriteCommandLCM(X, 1); //写入地址
switch(point_number)
{
case 0:
{
int_number = (unsigned int)Number; //取整
number_10bit = (int_number / 10); //取商,取出第一位数字
number_1bit = (int_number % 10); //取出第二位数字
break;
}
case 1:
{
int_number = (unsigned int)(Number * 10); //取整,化掉小数后一位小数
number_10bit = (int_number / 100); //取商,取出第一位数字
number_1bit = (int_number % 100 / 10); //取出第二位数字
number_point_1 = (int_number % 10); //取出第三位数字
break;
}
case 2:
{
int_number = (unsigned int)(Number * 100); //取整,化掉小数后两位小数
number_10bit = (int_number / 1000); //取商,取出第一位数字
number_1bit = (int_number % 1000 / 100); //取出第二位数字
number_point_1 = (int_number % 100 / 10); //取出第二位数字
number_point_2 = (int_number % 10); //取出第三位数字
break;
}
default:break;
}
if(number_10bit != 0)
{
WriteDataLCM(number_10bit + 0x30); //写入第一个字符
}
WriteDataLCM(number_1bit + 0x30); //写入第二个字符
if(point_number > 0)
{
WriteDataLCM(0x2E); //写入小数点
WriteDataLCM(number_point_1 + 0x30); //写入第一位小数
}
if(point_number > 1)
{
WriteDataLCM(number_point_2 + 0x30); //写入第二位小数
}
}
}
//5ms延时
void Delay5Ms(void)
{
unsigned int TempCyc = 5552;
while(TempCyc--);
}
//400ms延时
void Delay400Ms(void)
{
unsigned char TempCycA = 5;
unsigned int TempCycB;
while(TempCycA--)
{
TempCycB=7269;
while(TempCycB--);
};
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -