LCD1602显示屏在AVR单片机中的应用,9999倒数例子
时间:10-02
整理:3721RD
点击:
说明:本人很懒,例子只是在原作品上改动了一下代码。
/********************************************************
LCD1602显示实验
********************************************************/
#include<iom16v.h>
#include<macros.h>
#define uchar unsigned char
#define uint unsigned int
#define ulint unsigned long int
//#define DEBUG
#define LCD_DATA_PORT PORTB //定义LCD的D0-D7所在端口
#define LCD_DATA_POUT DDRB=0xFF //定义LCD数据端口为输出
#define LCD_DATA_PIN DDRB=0x00 //定义LCD数据端口为输入(在读LCD状态时用到)
#define LCD_Control_PORT PORTD //定义LCD的EN RW RS所在端口方便后面操作
#define LCD_Control_OUT DDRD|=(1<<DDA4)|(1<<DDA5)|(1<<DDA6)
#define LCD_Control_IN DDRD&=~((1<<DDA4)|(1<<DDA5)|(1<<DDA6))
#define LCD_EN_1 PORTD|=1<<PD4
#define LCD_EN_0 PORTD&=~(1<<PD4)
//LCD读写控制引脚
#define LCD_RW_1 PORTD|=1<<PD5
#define LCD_RW_0 PORTD&=~(1<<PD5)
//LCD指令或数据选择引脚
#define LCD_RS_1 PORTD|=1<<PD6
#define LCD_RS_0 PORTD&=~(1<<PD6)
uchar Data[6]={0,0,0,0,0,0};//显示初值,最后一个0是结束符,方便液晶显示
void nus_delay(uint nus);
void nms_delay(uint nms);
void mcu_io_init(void);
void lcd_init(void);
void LCD_en_write(void);
void wait_LCD_Ready(void);
void set_LCD_xy(uchar x, uchar y );
void LCD_write_onechar(uchar COMM,uchar DAT);
void LCD_write_string(uchar X,uchar Y,uchar *string);
void Sz(uint i,uchar *p) //显示处理,+48是因为液晶显示的是ASCII码
{
p[4]=i%10+48;//个
p[3]=i/10%10+48;//十
p[2]=i/100%10+48;//百
p[1]=i/1000%10+48;//千
p[0]=i/10000%10+48;//万
}
/****************************************************
函数名称:main
功能描述:主函数
输 入: 无
输 出: 无
日期:2009-4-8
*****************************************************/
void main(void)
{
uint j,i;
uchar START_DISPLAY1[]={" BK-AVR16A "};
mcu_io_init();
lcd_init();
LCD_write_string(0,0,START_DISPLAY1);
LCD_write_string(0,1,"TIME:");
while(1)
{
for(j=9999;j>1;j--)
//for(i=1;i<20;i++)
{
Sz(j,Data);
LCD_write_string(5,1,Data);
nms_delay(10);
}
}
}
/****************************************************
函数名称:mcu_io_init
功能描述:上电CPU IO口初始化
输 入: 无
输 出: 无
日期:2009-4-8
*****************************************************/
void mcu_io_init(void)
{
LCD_DATA_PORT=0xff;
LCD_DATA_POUT; //LCD数据口设为输出
LCD_EN_1;
LCD_RW_1;
LCD_RS_1;
LCD_Control_IN;
}
/****************************************************
函数名称:lcd_init
功能描述:LCD初始化
输 入: 无
输 出: 无
日期:2009-4-8
说明:注意初始化过程并加上适当延时
后面LCD的显示方式可按实际需要修改
*****************************************************/
void lcd_init(void)
{
nms_delay(15);
LCD_DATA_POUT;
LCD_Control_OUT;
LCD_write_onechar(0x38,0);
nms_delay(1);
LCD_write_onechar(0x38,0);
nms_delay(1);
LCD_write_onechar(0x38,0);
nms_delay(1);
LCD_write_onechar(0x38,0);
LCD_write_onechar(0x08,0); /*显示关闭*/
LCD_write_onechar(0x01,0); /*显示清屏*/
LCD_write_onechar(0x06,0); /*显示光标移动设置*/
nms_delay(1);;
LCD_write_onechar(0x0c,0); /*显示开及光标设置*/
}
/****************************************************
函数名称:LCD_en_write
功能描述:EN端产生一个脉冲,写LCD
输 入: 无
输 出: 无
日期:2009-4-8
*****************************************************/
void LCD_en_write(void)
{
LCD_EN_1;
nus_delay(150); //E脉冲周期最小150ns
LCD_EN_0;
}
/****************************************************
函数名称:wait_LCD_Ready
功能描述:判断LCD忙标志
输 入: 无
输 出: 无
日期:2009-4-8
*****************************************************/
void wait_LCD_Ready(void)
{
uchar temp1;
LCD_DATA_PORT=0XFF;
LCD_DATA_PIN; //D7设为输入,准备判断LCD忙标志
//1为忙 0为空闲
LCD_RS_0;
LCD_RW_1; //读
LCD_EN_1;
nus_delay(2);
while((temp1=PINC & 0X80));
LCD_EN_0;
LCD_RS_1;
LCD_DATA_POUT;
}
/****************************************************
函数名称:LCD_write_onechar
功能描述:写一个字节到LCD
输 入: COMM(指令) DAT(显示数据)
输 出: 无
日期:2009-4-8
*****************************************************/
void LCD_write_onechar(uchar COMM,uchar DAT)
{
wait_LCD_Ready(); //等待LCD空闲
LCD_RW_0; //写
//写数据
if(COMM==0)
{
LCD_RS_1; //RS高电平向LCD写数据
LCD_DATA_PORT=DAT;
}
//写命令
else
{
LCD_RS_0;
LCD_DATA_PORT=COMM;
}
LCD_en_write();
nus_delay(2);
LCD_RW_1;
LCD_RS_1;
}
/****************************************************
函数名称:LCD_write_string
功能描述:LCD字符串显示函数
输 入: x/y(X与Y坐标) *string(字符串首地址)
输 出: 无
日期:2009-4-8
*****************************************************/
void LCD_write_string(uchar X,uchar Y,uchar *string)
{
set_LCD_xy( X, Y ); //设置LCD显示坐标
while (*string)
{
LCD_write_onechar(0,*string );
string ++; //指向下一显示字符地址
}
}
/****************************************************
函数名称:set_LCD_xy
功能描述:设置显示坐标
输 入: x/y(X与Y坐标)
输 出: 无
日期:2009-4-8
说明: LMB1602第一行首地址为0x80
第二行为0xC0
日期:2009-4-7
*****************************************************/
void set_LCD_xy(uchar x, uchar y )
{
uchar DIS_address;
if (y == 0)
DIS_address = 0x80 + x; //第一行X列
else
DIS_address = 0xc0 + x;
LCD_write_onechar( DIS_address, 0 ); //第二行X列
}
/****************************************************
函数名称:nus_delay
功能描述:微秒级延时子程序
输 入: 无
输 出: 无
日期:2009-4-8
说明:
晶振为8M时
日期:2009-4-7
*****************************************************/
void nus_delay(uint nus)
{
int j=10;
while(nus--)
{
while(j--);
j=10;
}
}
/****************************************************
函数名称:nms_delay
功能描述:毫秒级延时子程序
输 入: 无
输 出: 无
日期:2009-4-8
说明:
晶振为8M时
*****************************************************/
void nms_delay(uint nms)
{
while(nms--)
nus_delay(1000);
}