/**********************************************************************
* 文件名称: main.c
* 程序作者: kidcao1987
* 程序版本: V1.0
* 功能描述: 装上LCD1602,在其上显示如下:
"This an IIC demo
1st data : 0x"
2nd data : 0x"
* 编译器:WinAVR-20090313
* 芯片:ATmega16,外部11.0592MHZ晶振
* 技术支持:
**********************************************************************/
#include
#include
#define SETLCD1602RS PORTA |= (1<#define CLRLCD1602RS PORTA &= ~(1<#define SETLCD1602RW PORTA |= (1<#define CLRLCD1602RW PORTA &= ~(1<#define SETLCD1602EN PORTA |= (1<#define CLRLCD1602EN PORTA &= ~(1<
#define IICDEVICEADDR 0xa0 //器件地址
//主机发送模式时的状态码,芯片手册P174
#define TW_START 0x08 //START已发出
#define TW_REP_START 0x10 //重复START已发出
#define TW_MT_SLA_ACK 0x18 //SLA+W已发出并收到ACK信号
#define TW_MT_SLA_NACK 0x20 //SLA+W已发出并收到NACK信号
#define TW_MT_DATA_ACK 0x28 //数据已发出并收到ACK信号
#define TW_MT_DATA_NACK 0x30 //数据已发出并收到NACK信号
#define TW_MT_ARB_LOST 0x38 //写字节或者数据的仲裁失败
//主机接收模式时的状态码,芯片手册P176
#define TW_MR_ARB_LOST 0x38 //丢失总线控制权或者未收到应答信号
#define TW_MR_SLA_ACK 0x40 //读命令已发出并收到ACK信号
#define TW_MR_SLA_NACK 0x48 //读命令已发出并收到NACK信号
#define TW_MR_DATA_ACK 0x50 //数据已收到并且返回ACK信号
#define TW_MR_DATA_NACK 0x58 //数据已收到并且返回NACK信号
unsigned char const ucString1[]={"This an IIC demo"};
unsigned char const ucString2[]={""};
unsigned char const ucString3[]={"1st data : 0x"};
unsigned char const ucString4[]={"2nd data : 0x"};
void LCD1602BusyCheck(void); //忙检测
void LCD1602WriteOperation(unsigned char,unsigned char); //写操作
void LCD1602Init(void); //初始化函数
void LCD1602MoveToPosition(unsigned char,unsigned char); //定位到制定位置
void LCD1602PrintString(unsigned char const * str); //输出一串字符
void IICInit(void); //初始化
void IICStart(void); //起始信号
void IICStop(void); //停止信号
void IICWriteOneChar(unsigned char); //写一个字节
unsigned char IICReadOneChar(unsigned char); //读一个字节,ack or nack
void IICWriteOneCharOnAddr(unsigned char,unsigned char); //在指定位置写一个字节
unsigned char IICReadOneCharFromAddr(unsigned char); //从指定位置读一个字节
int main(void)
{
PORTA = 0xFF;
DDRA = 0xFF;
PORTB = 0xFF;
DDRB = 0xFF;
PORTC = 0xFF;
DDRC = 0xFF;
LCD1602Init();
IICInit();
_delay_ms(2);
LCD1602MoveToPosition(0,0);
LCD1602PrintString(ucString1);
LCD1602MoveToPosition(1,0);
LCD1602PrintString(ucString2);
_delay_ms(2000);
//while(1);
IICWriteOneCharOnAddr(0x43,0x10); //在0x10,0x11两个测试位置写入两个数据,将其显示
IICWriteOneCharOnAddr(0x21,0x11);
LCD1602Init();
while(1)
{
LCD1602WriteOperation(0x01,0);
_delay_ms(2);
LCD1602MoveToPosition(0,0);
LCD1602PrintString(ucString3);
LCD1602WriteOperation(IICReadOneCharFromAddr(0x10)/16 + 48,1);
LCD1602WriteOperation(IICReadOneCharFromAddr(0x10)%16 + 48,1);
LCD1602MoveToPosition(1,0);
LCD1602PrintString(ucString4);
LCD1602WriteOperation(IICReadOneCharFromAddr(0x11)/16 + 48,1);
LCD1602WriteOperation(IICReadOneCharFromAddr(0x11)%16 + 48,1);
while(1);
}
}
//初始化
void IICInit()
{
TWSR = 0x00; //预分频系数为1
TWBR = 0x10; //波特率控制寄存器,波特率为153.6KHZ
TWAR = 0x00; //被控器地址寄存器,可以不设置,做为从机时必须设置
TWCR = (1 << TWEA) | (1 << TWEN); //TWEN使能TWI功能,PC0、PC1变成SCL、SDA引脚
//TWEA应答使能位
}
//起始信号
void IICStart(void)
{
TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); //清零中断标志位,申请成为主机,发送开始信号
while(!(TWCR & (1 << TWINT))); //检测中断标志,为1表明完成发送开始信号
//TWCR &= ~(1<}
//停止信号
void IICStop(void)
{
TWCR = (1 << TWINT) | (1 << TWSTO) | (1 << TWEN); //清零中断标志位,发送停止信号
}
//写一个字节
void IICWriteOneChar(unsigned char ucData)
{
//unsigned char ucAck;
TWDR = ucData; //放入数据寄存器
TWCR = (1 << TWINT) | (1 << TWEN); //清零中断标志位,开始发送数据
while(!(TWCR & (1<_delay_us(10);
/*if((TWSR & 0xf8) != TW_MT_SLA_ACK) //读取ACK信号
{
ucAck = 0; //没有返回ACK
}
else
{
ucAck = 1; //返回ACK
}*/
}
//读一个字节
unsigned char IICReadOneChar(unsigned char ucAck) //1-返回ACK信号,0-返回NACK信号
{
if (ucAck)
{
TWCR = (1<}
else
{
TWCR = (1<}
while(!(TWCR & (1 << TWINT))); //等待读取完成
return (TWDR); //返回读到的数据
}
//在指定位置写一个字节
void IICWriteOneCharOnAddr(unsigned char ucData,unsigned char ucAddr)
{
IICStart(); //起始信号
IICWriteOneChar(IICDEVICEADDR);//写器件地址
IICWriteOneChar(ucAddr); //写存储地址
IICWriteOneChar(ucData); //写数据
IICStop(); //停止信号
_delay_ms(10); //延时等待从机操作
}
/
//从指定位置读一个字节
unsigned char IICReadOneCharFromAddr(unsigned char ucAddr)
{
unsigned char ucBackValue = 0;
IICStart(); //起始信号
IICWriteOneChar(IICDEVICEADDR);//写器件地址
IICWriteOneChar(ucAddr); //写存储地址
IICStart(); //起始信号
IICWriteOneChar(IICDEVICEADDR | 0x01);//读器件地址
ucBackValue = IICReadOneChar(0); //无应答读取
IICStop(); //停止信号
return (ucBackValue);
}
//忙检测
void LCD1602BusyCheck(void)
{
unsigned char i = 254;
DDRB = 0x00; //设置最高位为输入
CLRLCD1602RS;
SETLCD1602RW;
SETLCD1602EN;
_delay_us(5);
while((i--) && (PINB & 0x80));
DDRB = 0xff;
_delay_us(5);
CLRLCD1602EN;
_delay_us(5);
}
//写操作
void LCD1602WriteOperation(unsigned char Data,unsigned char ComOrData)
{
LCD1602BusyCheck(); //ComOrData=0为命令,1为数据
if(0 == ComOrData)
CLRLCD1602RS;
else if(1 == ComOrData)
SETLCD1602RS;
CLRLCD1602RW;
SETLCD1602EN;
_delay_us(5);
PORTB = Data;
_delay_us(5);
CLRLCD1602EN;
_delay_us(100);
}
void LCD1602Init(void) //初始化
{
LCD1602WriteOperation(0x38,0);
_delay_ms(15);
LCD1602WriteOperation(0x38,0);
_delay_ms(5);
LCD1602WriteOperation(0x38,0);
_delay_ms(5);
LCD1602WriteOperation(0x38,0);
_delay_ms(5);
LCD1602WriteOperation(0x0c,0);
_delay_ms(1);
LCD1602WriteOperation(0x06,0);
_delay_ms(1);
LCD1602WriteOperation(0x01,0);
_delay_ms(1);
}
void LCD1602MoveToPosition(unsigned char ucx,unsigned char ucy)
{
if(0 == ucx) //第一行
{
LCD1602WriteOperation(0x80 + ucy,0); //第Y列
}
if(1 == ucx) //第二行
{
LCD1602WriteOperation(0xC0 + ucy,0); //第Y列
}
}
void LCD1602PrintString(unsigned char const * str)
{
while(*str != '\0')
{
LCD1602WriteOperation(*str,1);
str++;
}
}
视频地址:
阅读(1293) | 评论(0) | 转发(0) |