|
![](static/image/common/ico_lz.png)
楼主 |
发表于 2007-9-24 18:53:49
|
显示全部楼层
/***********************************************************************************
LCD1602液晶通过PCF8574转换成I2C接口驱动函数
LCD1602液晶与PCF8574之间的连接方式:
[LCD] PCF8574
1 GND- 8 GND
2 +5V- 16 VCC
3 VLC- LCD contrast control voltage 680欧电阻到地
4 RS - 5 P1 //RW低电平时,当RS=1 RW=0写数据;RS0 RW=0写指令
5 RW - 6 P2 //RW引脚始终置低电平
6 EN - 7 P3 //EN为读写使能端,高电平有效,下降沿锁定数据
11 D4 - 9 P4 //4位数据总线,要用PORT的高4位
12 D5 - 10 P5
13 D6 - 11 P6
14 D7 - 12 P7
作者:alien2006
时间:20070924
版本:V1.0
说明:LCD驱动采用4线驱动方法,LCD1602的RW端接低电平,这样无法读数据,操作需插入合适的
的延时,由于LCD1602是慢速器件,因此时序要注意,参考其手册
LCD第一行显示寄存器地址:0X80-0X8F
LCD第二行显示寄存器地址:0XC0-0XCF
PCF8754设置地址为0x40H
I2C接口线序定义为:1、SDA 2、Vdd 3、Vss 4、SCL
*************************************************************************************/
#include <avr/io.h>
#include <stdio.h>
#include <util/delay.h>
#include <util/twi.h>
#define PCF8574_Address 0x40 //PCF8574 I2C地址
#define TWI_Stop() TWCR=((1<<TWINT)|(1<<TWSTO)|(1<<TWEN))
#define TWI_Start() TWCR=((1<<TWINT)|(1<<TWSTA)|(1<<TWEN))
//--------------函数声明----------------------
static void TWI_Init(void);//TWI初始化
static unsigned char TWI_Send_A_Data(unsigned char Address, unsigned char Data);//TWI向指定的地址发送一个字节
static void DelayUS(unsigned int us); //----uS级延时
static void DelayMS(unsigned int ms); //----mS级延时
void LCD1602_Write_Command(unsigned char command); //向LCD1602写入指令
void LCD1602_Write_Data(unsigned char data); //向LCD1602写入数据
void LCD1602_Device_Init(void); //LCD1602初始化函数
void LCD1602_Set_Position(unsigned char x, unsigned char y); //向LCD1602设置下一个准备写入的字符位置
void LCD1602_Write_String(unsigned char X, unsigned char Y, char *String); //向指定的位置开始写字符串
unsigned char temp=0;
/*******************************************************************/
int main()
{
LCD1602_Device_Init();
while(1)
{
DelayMS(500);
LCD1602_Write_String(0, 0, "0123456789ABCDEF");
LCD1602_Write_String(0, 1, "0123456789abcdef");
DelayMS(500);
LCD1602_Write_String(0, 0, "hello! kitty1234");
LCD1602_Write_String(0, 1, "HELLO! KITTY5678");
}
return 0;
}
/*--------初始化TWI------------------------
函数名称:void TWI_Init(void)
函数参数:无
函数说明:初始化TWI
-----------------------------------------*/
void TWI_Init(void) //初始化TWI
{
TWCR= 0X00; //disable twi
TWBR= 0x20; //设置波特率
TWSR= 0x00; //设置预分频=1
TWCR= 0x04; //enable twi
}
/*-------TWI向指定的地址发送一个字节--------------
函数名称:void TWI_Send_A_Data(unsigned char Address, unsigned char Data)
TWI向指定的地址发送一个字节
函数参数:unsigned char Address //待发送的目的地址
unsigned char Data //待发送的数据
函数返回:unsigned char //1表示成功,其他返回状态码
函数说明:TWI向指定的地址发送一个字节
-------------------------------------------------*/
unsigned char TWI_Send_A_Data(unsigned char Address, unsigned char Data)//TWI向指定的地址发送一个字节
{
TWI_Start();//发送Start
while(!(TWCR & (1<<TWINT)));//等待START发送完毕,TWINT置位,并返回状态
if(TW_STATUS != TW_START) //检查发送完毕后的状态是否正确,如不正确则转向错误处理部分
{
//return TWSR;//出错则返回状态码
}
TWDR = Address|TW_WRITE;//写SLA+W到TWDR
TWCR = (1<<TWINT)|(1<<TWEN);//启动发送TWDR
while(!(TWCR & (1<<TWINT)));//等待TWDR发送SLA+W完毕TWINT置位,并返回状态
if((TW_STATUS == TW_MT_SLA_ACK)||(TW_STATUS == TW_MT_SLA_NACK))//检查返回的状态是否正确
{
//return TWSR;
}
TWDR = Data;//装载要发送的数据
TWCR = (1<<TWINT)|(1<<TWEN);//启动发送TWDR
while(!(TWCR & (1<<TWINT)));//等待TWDR发送DATA完毕,TWINT置位,并返回状态
if(TW_STATUS != TW_MT_DATA_ACK)//检查DATA发送返回状态是否正确
{
//return TWSR;
}
TWI_Stop();//结束本次发送
return 1;
}
//----------------ms级延时---------------
void DelayMS(unsigned int ms) //----mS级延时
{
unsigned int i;
for(i=0; i<ms; i++) _delay_ms(1);
}
//----------------us级延时---------------
void DelayUS(unsigned int us) //----uS级延时
{
unsigned int i;
for(i=0; i<us; i++) _delay_us(1);
}
/*------------向LCD1602写入指令----------------------------
函数名称:void LCD1602_Write_Command(unsigned char command)
向LCD1602写入指令
函数参数:unsigned char command //准备写入的指令
函数说明:向LCD1602的指令寄存器写入一个指令
---------------------------------------------------------------*/
void LCD1602_Write_Command(unsigned char command) //向LCD1602写入指令
{
//unsigned char temp=0;
DelayUS(17);//此处插入一个等待很重要,小于这个时间会导致连续写时出现错误
//先写入高4位
temp = command&0xF0;//先处理高4位,EN=0,RW=0,RS=0
TWI_Send_A_Data(PCF8574_Address, temp);
temp |= 0x08; //拉高EN
TWI_Send_A_Data(PCF8574_Address, temp);
temp &= 0xf7; //EN置低,下降沿写入液晶
TWI_Send_A_Data(PCF8574_Address, temp);
//接下来写入低4位
temp = command<<4;
TWI_Send_A_Data(PCF8574_Address, temp);
temp |= 0x08; //拉高EN
TWI_Send_A_Data(PCF8574_Address, temp);
temp &= 0xf7; //EN置低,下降沿写入液晶
TWI_Send_A_Data(PCF8574_Address, temp);
}
/*------------向LCD1602写入数据----------------------------
函数名称:void LCD1602_Write_Data(unsigned char data)
向LCD1602写入数据
函数参数:unsigned char data //准备写入的数据
函数说明:向LCD1602的指令寄存器写入一个数据
---------------------------------------------------------------*/
void LCD1602_Write_Data(unsigned char data) //向LCD1602写入数据
{
//unsigned char temp=0;
DelayUS(17);//此处插入一个等待很重要,小于这个时间会导致连续写时出现错误
//先写入高4位
temp = (data&0xF0)|0x02;//先处理高4位,EN=0,RW=0,RS=1
TWI_Send_A_Data(PCF8574_Address, temp);
temp |= 0x08; //拉高EN
TWI_Send_A_Data(PCF8574_Address, temp);
temp &= 0xf7; //EN置低,下降沿写入液晶
TWI_Send_A_Data(PCF8574_Address, temp);
//接下来写入低4位
temp = (data<<4)|0x02;
TWI_Send_A_Data(PCF8574_Address, temp);
temp |= 0x08; //拉高EN
TWI_Send_A_Data(PCF8574_Address, temp);
temp &= 0xf7; //EN置低,下降沿写入液晶
TWI_Send_A_Data(PCF8574_Address, temp);
}
/*------------------------------------------------------------------
函数名称:void LCD1602_Init(void)//LCD1602初始化函数
函数参数:无
函数说明:参考LCD1602液晶说明手册
------------------------------------------------------------------*/
void LCD1602_Device_Init(void) //LCD1602初始化函数
{
TWI_Init();
DelayMS(50); //先等待50毫秒VDD上电稳定
LCD1602_Write_Command(0x28);//先进行功能设置,四位数据接口,两行显示,5′7点阵字符。
DelayUS(40); //等待上条指令完成
LCD1602_Write_Command(0x0C);//Display On/Off Control,显示开关:D=1为开,光标开关:C=1为开,闪烁开关:B=1为开
//LCD1602_Write_Command(0x06);//AC地址递增模式
//DelayMS(2);
LCD1602_Write_Command(0x01);//清屏
DelayMS(2);
}
/*--------设置AC地址--------------------------------------------------
函数名称:void LCD1602_Set_Position(unsigned char x, unsigned char y)
向LCD1602设置下一个准备写入的字符位置
函数参数:unsigned char x 行地址 0~F
unsigned char y 列地址 0~1
函数说明:设置AC地址,
---------------------------------------------------------------------*/
void LCD1602_Set_Position(unsigned char x, unsigned char y) //向LCD1602设置下一个准备写入的字符位置
{
unsigned char address = (y == 0) ? (0x80 + x) : (0xC0 + x);
LCD1602_Write_Command(address);
}
/*--------向指定的位置开始写字符串 ---------------------------------------
函数名称:LCD1602_Write_String(unsigned char X, unsigned char Y, char *s)
向指定的位置开始写字符串
函数参数:unsigned char X //列位置
unsigned char Y //行位置
char *String //要显示的字符串
函数说明:向指定的位置开始写字符串
------------------------------------------------------------------------*/
void LCD1602_Write_String(unsigned char X, unsigned char Y, char *String) //向指定的位置开始写字符串
{
LCD1602_Set_Position(X, Y);
while(*String)
{
LCD1602_Write_Data(*String++);
}
}
再分享下调试成功的源代码. |
|