1602的四位數據線程序,節省了IO。單片機用的是Atmega16,編譯環境ICC6.31A,1602驅動頭文件。
1602Driver.h
/*********************LCD模塊1602底層驅動庫***********************
* LCD模塊與單片機的硬件連接:
* /端口名稱 /端口符號 /MCU端口 / LCD引腳號/
*
* RS數據/指令選擇線
* RS PD3 4
* R/W讀寫選擇線
* R/W GND 5
* EN寫使能線
* EN PD2 6
* 三態雙向數據總線
* D0-D3 NC 7-10
* D4 PD4 11
* D5 PD5 12
* D6 PD6 13
* D7 PD7 14
*
* 其他端口連接:
* 電源負 VSS 1
* 電源正+4.5--+5.5V VDD 2
* 對比度調節 VL GND 3
* 背光負 BLK NC 15
* 背光正 BLA NC 16
* 說明:采用節省端口的4線線連接方式,即將8位的數據分兩次傳輸;同
* 時將R/W接地RW(只用W不需要R,所以可以省一根線)
* 日期:2006/02/03
*****************************************************************/
/*****************定義MCU與LCD的接口******************/
#define LCD_EN_PORT PORTC //寫使能。高有效,下降沿時鎖定數據
#define LCD_RS_PORT PORTC //指令/數據選擇
#define LCD_DATA_PORT PORTC //數據總線
#define LCD_EN 0x04 //PORTD2 out
#define LCD_RS 0x08 //PORTD3 out
#define LCD_DATA 0xf0 //PORTD4/5/6/7 out
#define Data_Write LCD_RS_PORT |= LCD_RS //寫數據模式
#define Command_Write LCD_RS_PORT &= ~LCD_RS //寫指令模式
#define Write_En LCD_EN_PORT |= LCD_EN //寫使能
#define Write_Lock LCD_EN_PORT &= ~LCD_EN //鎖定數據
//#define Graph_Right_Run LCD_Write_Char(0x02,0) //畫面右移
const char CHR[16] = {'0','1','2','3','4','5','6','7','8'
,'9','a','b','c','d','e','f'};
unsigned char LCD_Buff[] = {0,0,0,0,0,0,0,0};
/*******************N us延時函數**********************/
void Delay_nus(unsigned int j)
{
unsigned int i="0";
for(i=j;i>0;i--)
{
asm("nop");
}
}
/********************N ms延時函數*********************/
void Delay_nms(unsigned int n)
{
unsigned int m = 0;
unsigned int k = 0;
for (m=n;m>0;m--)
{
for (k=1140;k>0;k--)
{
Delay_nus(1);
}
}
}
/******讀寫使能(高電平有效,下降沿鎖定數據 )********/
void Write_Enable(void)
{
Write_En;
Delay_nus(1);
Write_Lock;
}
/*---------------------------------------------------------------------
* LCD_Write_Char :英文單字符顯示函數
*
* 向LCD發送數據/指令。 Command="1" 發送顯示數據
* Command=0 發送指令數據
*
* 輸入參數 :Command 數據/指令寄存器選擇
* Data 顯示內容
*
-----------------------------------------------------------------------*/
void LCD_Write_Char(char Command,char Data)
{
unsigned Command_Temp,Data_Temp;
Command_Temp = Command;
Data_Temp = Data;
Delay_nms(1); //延時1ms,以避開"寫繁忙"時期
if (Command == 0) //數據輸入模式
{
Data_Write;
LCD_DATA_PORT &= 0x0f; //數據口清零
LCD_DATA_PORT |= Data_Temp&0xf0; //先送高4位
}
else //指令輸入模式
{
Command_Write;
LCD_DATA_PORT &= 0x0f;
LCD_DATA_PORT |= Command_Temp&0xf0;
}
Write_Enable();
Command_Temp=Command_Temp << 4;
Data_Temp=Data_Temp << 4;
LCD_DATA_PORT &= 0X0F; //數據口清零
if (Command==0) //再送低4位
{
LCD_DATA_PORT |= Data_Temp&0xf0;
}
else
{
LCD_DATA_PORT |= Command_Temp&0xf0;
}
Write_Enable();
}
/***********LCD模塊初始化**************/
void LCD_Init(void)
{
Delay_nms(5);
LCD_Write_Char(0x28,0); //4位數據線格式
Delay_nus(10);
LCD_Write_Char(0x0d,0); //顯示開,光標閃爍
Delay_nus(10);
LCD_Write_Char(0x01,0); //清屏
Delay_nms(1);
LCD_Write_Char(0x06,0); //光標模式設置
}
/*-----------------------------------------------------------------------
* Locate : 設置LCD顯示的起始位置
*
* 輸入參數:x、y : 顯示字符串的位置,X:0-1,Y:0-15
* LCD第一行顯示寄存器地址:0X80-0X8F
* LCD第一行顯示寄存器地址:0XC0-0XCF
-----------------------------------------------------------------------*/
void Locate( unsigned char x, unsigned char y )
{
unsigned char Address;
if (x == 0)
Address = 0x80 + y; //第一行顯示的地址
else
Address = 0xc0 + y; //第二行顯示的地址
LCD_Write_Char(Address,0);
}
/*-----------------------------------------------------------------------
* LCD_Write_String : 英文字符串顯示函數
*
* 輸入參數:*s :英文字符串指針
* X、Y :顯示字符串的位置
-----------------------------------------------------------------------*/
void LCD_Write_String(unsigned char X,unsigned char Y,unsigned char *String)
{
Locate( X, Y); //先送顯示起始坐標
while (*String) //再依次送顯示字符
{
LCD_Write_Char( 0, *String );
String ++;
}
}
/*-----------------------------------------------------------------------
* DEC_Num_Disp :10進制數值顯示函數
*
* 輸入參數 :X 字符起始顯示行坐標2
* Y 字符起始顯示列坐標
* Num 需要顯示的數值(最長8位)
* Bit 有效顯示的位數
* 輸出 :
-----------------------------------------------------------------------*/
void DEC_Num_Disp(unsigned char X,unsigned char Y,unsigned long Num,char Bit)
{
unsigned char i = 0;
Locate( X, Y );
for (i=0 ; i<Bit ; i++)
{
LCD_Buff[i] = CHR[Num%10];
Num = Num/10;
}
for (i=0 ; i<Bit ; i++)
{
LCD_Write_Char(0,LCD_Buff[Bit-i-1]); //先寫高位再寫低位
}
}
/*-----------------------------------------------------------------------
* HEX_Num_Disp :16進制數值顯示函數
*
* 輸入參數 :X 字符起始顯示行坐標
* Y 字符起始顯示列坐標
* Num 需要顯示的數值(最長8位)
* Bit 有效顯示的位數
* 輸出 :
-----------------------------------------------------------------------*/
void HEX_Num_Disp(unsigned char X,unsigned char Y,unsigned long Num,char Bit)
{
char a = 0;
Locate( X, Y );
for(a=8-Bit ; a<8 ; a++)
{
LCD_Write_Char(0,CHR[(Num<< (a << 2)) >>28]);
}
}
1602測試程序LCD.c
/*********************************************
* "1602Driver.h"庫測試程序
*********************************************/
#include <iom16v.h>
#include "1602Driver.h"
void Port_Init(void)
{
DDRD = 0xff;
DDRC = 0xff;
}
void main (void)
{
int counter;
OSCCAL="0XA5";
Port_Init();
LCD_Init();
LCD_Write_Char(0x01,0); //清屏
HEX_Num_Disp(0,0,13,1);
DEC_Num_Disp(0,1,4,1);
//LCD_Write_String(2,0,"T");
LCD_Write_String(1,0,"Disp");
while(1);
}