|
本帖最后由 gxg0000 于 2018-2-1 21:08 编辑
带有PCF8574模块板的lcd1602液晶显示屏,价格便宜,该显示模块通过4线连接单片机(其中2根串行数据接口,2根正负电源),能够大大简化电路连接,感兴趣的朋友不妨移植到含有I2C总线接口的单片机上。
本驱动程序已通过proteus仿真和测试板。
- #include<avr/io.h>
- #include <util/delay.h>
- /************************************************************************
- * PCF8574单向写
- *************************************************************************/
- //TWI状态定义
- #define MT_SLA_ACK 0x18 //SLA+W 已发送,接收到ACK(SLA从机地址)
- #define MT_DATA_ACK 0x28 //数据已发送,接收到ACK
- #define WD_DEVICE_ADDR 0x4e //PCF8574地址,高七位是从机I2C地址,第0位是传输方向
- //常用TWI操作(主模式写)
- #define Start() (TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN))
- #define Stop() (TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN))
- #define Wait() {while (!(TWCR & (1<<TWINT)));}
- #define TestAck() (TWSR & 0xf8)
- #define SetAck() (TWCR |= (1<<TWEA))
- #define SetNoAck() (TWCR &=~ (1<<TWEA))
- #define Write8Bit(x) {TWDR =(x);TWCR=(1<<TWINT)|(1<<TWEN);}
- /************************************************************************
- * TWI总线初始化函数
- *************************************************************************/
- void I2C_init(void)
- {
- TWCR=0x0;
- TWBR=0x20; //设置波特率
- TWSR=0x0; //设置预分频=1
- TWCR=0x04; //使能总线激活
- }
- /************************************************************************
- * 向I2C写1字节函数
- *************************************************************************/
- unsigned char I2C_Write(unsigned char data)
- {
- Start(); //启动
- Wait(); //等待
- //TestAck()!=START) return 1; //有错误返回1
- Write8Bit(WD_DEVICE_ADDR); //从机I2C地址,写PCF8574地址(0x27)
- Wait();
- //TestAck()!=MT_SLA_ACK) return 1; //有错误返回1
- Write8Bit(data); //写命令/数据
- Wait();
- //TestAck()!=MT_DATA_ACK) return 1; //有错误返回1
- Stop();
- return 0;
- }
- /************************************************************************
- * 1602写指令或写数据
- *************************************************************************/
- void write_ComData(unsigned char rs,unsigned char dat) //LCD1602写指令或写数据函数(rs=0写命令,re=1写数据)
- {
- unsigned char port=0; //PCF8574 I/O映射
- if(rs==0)
- {
- port=0x0;
- I2C_Write(port); //写命令
- }
- else
- {
- port=0x1;
- I2C_Write(port); //写数据
- }
- port &= 0x0f; //清4位数据总线
- port |= (dat&0xf0); //合成高4位
- I2C_Write(port); //输出
- port |=(1<<2);
- I2C_Write(port); //E=1
- _delay_us(1);
- port &=~(1<<2);
- I2C_Write(port); //E=0
- port &= 0x0f;
- port |= (dat<<4); //合成低4位
- I2C_Write(port); //输出
- port |=(1<<2);
- I2C_Write(port); //E=1
- _delay_us(1);
- port &=~(1<<2);
- I2C_Write(port); //E=0
- _delay_ms(1);
- }
- /************************************************************************
- * 1602初始化
- *************************************************************************/
- void init(void)
- {
- //设置数据总线8位(CPU复位操作,先退出液晶显示器处在4位总线模式,然后重新设置数据总线4位)
- _delay_ms(15); //延时15ms
- write_ComData(0,0x38); //设置数据总线8位
- _delay_ms(15); //延时5ms
- //转到4位总线方式
- I2C_Write(0x0);
- _delay_us(1);
- I2C_Write(0x20);
- _delay_us(1);
- I2C_Write(0x24); //E=1
- _delay_us(1);
- I2C_Write(0x20); //E=0
- _delay_ms(15);
- write_ComData(0,0x28); //重新设置数据总线4位,2行,5*7点阵字符
- write_ComData(0,0x0c); //整体显示,关光标
- write_ComData(0,0x01); //清屏
- _delay_ms(2);
- }
- /************************************************************************
- * 主函数
- *************************************************************************/
- int main(void)
- {
- unsigned char table1[] = {"gxg000@hotmail.c"};
- unsigned char table2[] = {"I2C_LCD1602 ok!"};
- I2C_init();
- init();
- while(1)
- {
- for(unsigned char i=0;i<16;i++)
- {
- write_ComData(0,0x80+i); //置第1行首地址
- write_ComData(1,table1[i]); //显示"gxg000@hotmail.c"
- }
- for(unsigned char i=0;i<16;i++)
- {
- write_ComData(0,0xc0+i); //置第2行首地址
- write_ComData(1,table2[i]); //显示"I2C_LCD1602 ok!"
- }
- _delay_ms(700);
- }
- }
复制代码 |
|