总结一下一些模块常用的子程序
相信很多同学和我一样,刚开始的时候可能不太喜欢拿着数据手册去看,然后去写一些子程序。比如说lcd12864或者lcd1602的一些写命令、写数据、忙检查子程序等等。
这里给大家总结一些模块的子程序,大家直接可以复制粘贴拿来用。
LCD12864模块
下面是实际使用lcd12864模块的子程序,当然如果大家买的模块带中文字库,可以直接查找字库表显示中文汉字。或者直接将中文字符串进行输出显示。
/*******************************************************************
函数名称:delay(int ms)
函数功能:延时
输入参数:ms 要延时的ms数
返回值: 无
*******************************************************************/
void delay_ms(int ms)
{
while(ms--)
{
uchar i;
for(i=0;i<250;i++){; ; ; ;} //一个机器周期为1us,250*4us=1ms
}
}
/*******************************************************************
函数名称:lcd_busy()
函数功能:检测LCD忙状态。
输入参数:无
返回值: result result为1时,忙等待;result为0时,闲,可写指令数据
*******************************************************************/
bit lcd_busy()
{
bit result; //定义是否忙碌标志位
LCD_RS = 0;
LCD_RW = 1;
LCD_EN = 1;
delay_ms(1);
result = (bit)(LCD_data&0x80);
LCD_EN = 0;
return(result);
}
/*******************************************************************
函数名称:lcd_wcmd()
函数功能:lcd写指令数据子程序。
输入参数:cmd 输入命令
返回值: 无
*******************************************************************/
void lcd_wcmd(uchar cmd)
{
while(lcd_busy());
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
delay_ms(1);
LCD_data = cmd; //将指令数据送入P0口
delay_ms(1);
LCD_EN = 1;
delay_ms(1);
LCD_EN = 0;
}
/*******************************************************************
函数名称:lcd_wdat()
函数功能:lcd写显示数据子程序。
输入参数:dat 显示的数据
返回值: 无
*******************************************************************/
void lcd_wdat(uchar dat)
{
while(lcd_busy());
LCD_RS = 1;
LCD_RW = 0;
LCD_EN = 0;
LCD_data = dat; //将显示数据送入P0口
delay_ms(1);
LCD_EN = 1;
delay_ms(1);
LCD_EN = 0;
}
/*******************************************************************
函数名称:lcd_init()
函数功能:lcd初始化子程序。
输入参数:无
返回值: 无
*******************************************************************/
void lcd_init()
{
lcd_wcmd(0x34); //扩充指令操作
delay_ms(5);
lcd_wcmd(0x30); //基本指令操作
delay_ms(5);
lcd_wcmd(0x0C); //显示开,关光标
delay_ms(5);
lcd_wcmd(0x01); //清除LCD的显示内容
delay_ms(5);
}
/*******************************************************************
函数名称:lcd_pos()
函数功能:lcd设定显示位置子程序。
输入参数:X:行数 Y:列数
返回值: 无
*******************************************************************/
void lcd_pos(uchar X,uchar Y)
{
uchar pos;
if(X==0)X=0x80; //设置为第1行,注意对应X是0
else if(X==1)X=0x90;
else if(X==2)X=0x88;
else if(X==3)X=0x98;
pos = X+Y ; //设置列,注意第一列对应Y是0
lcd_wcmd(pos); //设定显示地址
}
/*******************************************************************
函数名称:lcd_display()
函数功能:lcd设定显示位置并显示字符串子程序,包括中英文、数字、特殊字符。
输入参数:X:行数 Y:列数 *dis 字符串地址
返回值: 无
*******************************************************************/
void lcd_display (uchar X,uchar Y,uchar *dis)
{
uchar i;
lcd_pos(X,Y);
i = 0;
while(dis[i] != '\0') //显示字符串
{
lcd_wdat(dis[i]);
i++;
}
}
很多同学在做仿真的时候代码和实际的不太一样。比如用proteus仿真时lcd12864有CS1,CS2两个片选信号引脚,但是实际的时候大多数是没有这两个引脚,而是一个PSB引脚(当然淘宝上也有带CS1,CS2片选引脚的lcd12864买)。接下来给大家总结一下仿真时如果用CS1,CS2片选引脚应该怎么写这些子程序。
void delay_ms(uint xms) //延时子程序
{
uint i,j;
for(i=xms;i>0;i--)
{
for(j=110;j>0;j--);
}
}
void lcd_busy() //LCD忙检查子程序
{
uchar result;
LCD_RS=0;
LCD_RW=1;
do
{
LCD_data=0x00;
LCD_EN=1;
_nop_();
result=LCD_data;
LCD_EN=0;
result=0x80&result; //检查忙信号
}while(!(result==0x00)); //当忙信号为0时才可继续操作
}
void lcd_wcmd(uchar cmd) //LCD写命令子程序
{
lcd_busy();
LCD_RS=0; //写命令
LCD_RW=0;
LCD_data=cmd;
LCD_EN=1; //利用EN 下降沿完成命令写操作
_nop_();
_nop_();
LCD_EN=0;
}
void SetPage(uchar page) //设置页码子程序,页码为0~7
{
page=0xb8|page;
lcd_wcmd(page);
}
void SetStartLine(uchar startline) //设置起始行,行号为0~63
{
startline=0xc0|startline;
lcd_wcmd(startline);
}
void SetColumn(uchar column) //设置列子程序,列号为0~63
{
column=column&0x3f;
column=0x40|column;
lcd_wcmd(column);
}
void SetOnOff(uchar onoff) //开关显示屏子程序
{
onoff=0x3e|onoff;
lcd_wcmd(onoff);
}
void lcd_wdat(uchar dat) //LCD写数据子程序
{
lcd_busy();
LCD_RS=1;
LCD_RW=0;
LCD_data=dat;
LCD_EN=1;
_nop_();
_nop_();
LCD_EN=0;
}
void SelectScreen(uchar screen) //选屏子程序,screen=0,1,2
{
switch(screen)
{
case 0: CS1=0; //全屏显示
_nop_();
_nop_();
_nop_();
CS2=0;
_nop_();
_nop_();
_nop_();
break;
case 1: CS1=0; //左屏显示
_nop_();
_nop_();
_nop_();
CS2=1;
_nop_();
_nop_();
_nop_();
break;
case 2: CS1=1; //右屏显示
_nop_();
_nop_();
_nop_();
CS2=0;
_nop_();
_nop_();
_nop_();
break;
}
}
void ClearScreen(uchar screen) //清屏子程序,screen=0,1,2
{
uchar i,j;
SelectScreen(screen);
for(i=0;i<8;i++)
{
SetPage(i);
SetColumn(0);
for(j=0;j<64;j++)
{
lcd_wdat(0x00);
}
}
}
void lcd_init() //lcd12864初始化子程序
{
lcd_busy(); //读忙信号,不忙则向下执行
SelectScreen(0);
SetOnOff(0); //关屏
SelectScreen(0);
SetOnOff(1); //开屏
SelectScreen(0);
ClearScreen(0); //清屏
SetStartLine(0); //开始行为0
}
void ChineseDisplay(uchar screen,uchar page,uchar column,uchar number) //汉字显示子程序
{
int i;
SelectScreen(screen); //screen为显示的屏号
column=column&0x3f; //column为列号
SetPage(page); //page为页号,显示第number个汉字的上半部分,可理解为要显示的汉字位于屏幕的第page行
SetColumn(column);
for(i=0;i<16;i++)
{
lcd_wdat(Chinese[i+32*number]);//number为字号,取第number个汉字的第i列数据编码值
}
SetPage(page+1); //显示第number个汉字的下半部分
SetColumn(column);
for(i=0;i<16;i++)
{
lcd_wdat(Chinese[i+32*number+16]);//取第number个汉字的第i列数据编码值
}
}
下篇:DS1302时钟模块
链接: 下篇:DS1302时钟模块