/*******************************************************************
* *
* ME850单片机开发实验仪演示程序 - 24C04读写 *
* *
* 8位数码管显示 *
* *
* 时间: 2008/08/20 *
* 作者: gguoqing (gguoqing@willar.com) *
* 网站: www.sofi-tech.com(硕飞科技) www.mcusj.com(伟纳单片机世界) *
* 邮箱: sofitech@tom.com *
* *
*【版权】Copyright(C)伟纳电子 www.willar.com All Rights Reserved *
*【声明】此程序仅用于学习与参考,引用请注明版权和作者信息! *
* *
********************************************************************
* *
* 将0-7显示数据先写入24C04芯片,再将其数据逐个读出送数码管显示。 *
* *
*******************************************************************/
#include <reg52.h>
#include <intrins.h>
#define OP_WRITE 0xa0 // 器件地址以及写入操作
#define OP_READ 0xa1 // 器件地址以及读取操作
unsigned char data display[] =
{
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0
};
unsigned char code sendbuf[] =
{
0xc0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90
};
sbit SDA = P2 ^ 6;
sbit SCL = P2^ 7;
char code reserve[3]_at_ 0x3b; //保留0x3b开始的3个字节
/**********************************************************
延时子程序 (4.34us)
**********************************************************/
void delayNOP(void)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
/**********************************************************
延时子程序
**********************************************************/
void delayms(unsigned int ms)
{
unsigned char k;
while (ms--)
{
for (k = 0; k < 114; k++)
;
}
}
/**********************************************************
启动子程序
在 SCL 高电平期间 SDA 发生负跳变
**********************************************************/
void iic_start()
{
SDA = 1;
SCL = 1;
delayNOP();
SDA = 0;
delayNOP();
SCL = 0;
}
/**********************************************************
停止子函数
在 SCL 高电平期间 SDA 发生正跳变
**********************************************************/
void iic_stop()
{
SDA = 0;
SCL = 1;
delayNOP();
SDA = 1;
delayNOP();
SCL = 0;
}
/**********************************************************
IIC初始化子程序
**********************************************************/
void iic_init()
{
SCL = 0;
iic_stop();
}
/**********************************************************
发送应答位子函数
在 SDA 低电平期间 SCL 发生一个正脉冲
**********************************************************/
void iic_ack()
{
SDA = 0;
SCL = 1;
delayNOP();
SCL = 0;
SDA = 1;
}
/**********************************************************
发送非应答位子函数
在 SDA 高电平期间 SCL 发生一个正脉冲
**********************************************************/
void iic_noack()
{
SDA = 1;
SCL = 1;
delayNOP();
SCL = 0;
SDA = 0;
}
/**********************************************************
应答位检测子函数
**********************************************************/
/*
bit iic_testack()
{
bit ack_bit;
SDA = 1; //置SDA为输入方式
SCL = 1;
delayNOP();
ack_bit = SDA;
SCL = 0;
delayNOP();
return ack_bit; //返回AT24C04应答位
}
*/
/**********************************************************
读一个字节子程序
从AT24C04读数据到MCU
**********************************************************/
/*
unsigned char readbyte()
{
unsigned char i,read_data;
for(i = 0; i < 8; i++)
{
read_data <<= 1;
if(iic_testack())
read_data++;
}
return(read_data);
}
*/
/**********************************************************
读一个字节子程序
从AT24C04读数据到MCU
**********************************************************/
unsigned char readbyte()
{
unsigned char i, read_data;
SDA = 1; //置SDA为输入方式
for (i = 0; i < 8; i++)
{
SCL = 1; //使SDA数据有效
read_data <<= 1; //调整接收位
if (SDA)
//读SDA
read_data++;
SCL = 0; //继续接收数据
}
return (read_data);
}
/**********************************************************
发送一个字节子程序
从MCU移出数据到AT24C04
**********************************************************/
void writebyte(unsigned char write_data)
{
unsigned char i;
for (i = 0; i < 8; i++)
// 循环移入8个位
{
SDA = (bit)(write_data &0x80); //将发送位送入SDA数据线
SCL = 1;
delayNOP();
SCL = 0; //SDA数据线上数据变化
write_data <<= 1; //调整发送位
}
}
/**********************************************************
在指定地址addr处写入N个数据
**********************************************************/
void write_nbyte(unsigned char addr, unsigned char n)
{
unsigned char x;
iic_start();
writebyte(OP_WRITE); //写0xa0
iic_ack();
writebyte(addr); //写存储地址
iic_ack();
while (n--)
{
writebyte(sendbuf[x++]); //写数据
iic_ack();
delayms(1);
}
iic_stop(); //发送结束
}
/**********************************************************
在指定地址addr处读出N个数据
**********************************************************/
void read_nbyte(unsigned char addr, unsigned char n)
{
unsigned char x = 0;
iic_start();
writebyte(OP_WRITE); //写0xa0
iic_ack();
writebyte(addr); //写读取地址
iic_ack();
iic_start();
writebyte(OP_READ); //写0xa1
iic_ack();
while (n--)
{
display[x++] = readbyte(); //读出数据写入相应显存单元
iic_ack(); //发送应答位
delayms(1);
}
iic_noack(); //发送非应答位
iic_stop(); //发送结束
}
/**********************************************************
主函数
**********************************************************/
void main(void)
{
unsigned char k, shift;
iic_init();
write_nbyte(0, 8); //写入显示代码到AT24C04
delayms(100); //延时100ms,等待芯片自动编程完毕
read_nbyte(0, 8); //从AT24C04读出显示代码
while (1)
{
shift = 0xfe; //位码初始值
P2 = 0xff; //关闭显示
for (k = 0; k < 8; k++)
{
P0 = display[k]; //段码输出
P2 = shift; //位码输出
shift = _crol_(shift, 1); //修改位码
delayms(1); //延时1ms
}
}
}
/**********************************************************/