|
看到有兄弟要,就发上来了。以前我朋友用WinAVR写的,改的是ZLG的C51代码,用WinAVR20040404可以正常编译运行。
//#####################---文件信息-----############################
//文 件 名 : 7290.c
//创 建 人 : www.fcdpj.com
//建 立 时 间 : 2004-2-17
//版 本 描 述 : V1.0
//功 能 描 述 : ZLG7290使用代码 ,使用模拟I2C
//备 注 : 调试环境为AVRGCC 3.3.1,MCU为Mega8 晶振为3.6864MHZ
// 由于ZLG7290的速度很慢,换晶振时注意延时程序的调整.实际测试中
// 死机现象比较严重,建议使用控制ZLG7290的复位
//最后修改时间 : 2004-2-19
//##################################################################
#include "7290.h"
//0到9
//const u08 LED_Font[10] = {0xCF,0x60,0xDA,0xF2,0x66,0xB6,0xBE,0xE0,0xFE,0xF6}; //正
const u08 LED_Font[10] = {0xfc,0x0c,0xda,0x9e,0x2e,0xb6,0xf6,0x1c,0xfe,0xbe}; //反
//----------------------------------------------------------------
void I2c_Send_Byte(u08 data);
u08 I2c_Rev_Byte(void);
//*****************************************************************
//函 数 名 : _Nop
//建 立 时 间 : 2004-2-17
//功 能 描 述 : 延时函数,最大值为0xff
//备 注 : 没有返回值
//最后修改时间 : 2004-2-18
//*****************************************************************
void _Nop(u08 dly)
{
u08 i;
for(i=0;i<dly;i++)
{
asm("nop");
}
}
//==============================================
//I2C通讯协议实现部分
//==============================================
//*****************************************************************
//函 数 名 : Start_I2c
//建 立 时 间 : 2004-2-17
//功 能 描 述 : 启动模拟I2C通讯
//备 注 : 没有返回值
//最后修改时间 : 2004-2-17
//*****************************************************************
void Start_I2c(void)
{
SDA_1; //发送起始条件的数据信号
_Nop(1);
SCL_1;
_Nop(5); //起始条件建立时间大于4.7us,延时
SDA_0; //发送起始信号
_Nop(5); // 起始条件锁定时间大于4μs
SCL_0; //钳住I2C总线,准备发送或接收数据
_Nop(5);
}
//*****************************************************************
//函 数 名 : Stop_I2c
//建 立 时 间 : 2004-2-17
//功 能 描 述 : 停止模拟I2C通讯
//备 注 : 没有返回值
//最后修改时间 : 2004-2-17
//*****************************************************************
void Stop_I2c(void)
{
SDA_0 //发送结束条件的数据信号
_Nop(1);
SCL_1 //结束条件建立时间大于4μs
_Nop(5);
SDA_1 //发送I2C总线结束信号
_Nop(5);
}
//*****************************************************************
//函 数 名 : I2c_Send_Byte
//建 立 时 间 : 2004-2-17
//功 能 描 述 : 向I2c总线发送1个字节的数据/命令
//备 注 : 没有返回值
//最后修改时间 : 2004-2-18
//*****************************************************************
void I2c_Send_Byte(u08 data)
{
u08 BitCnt;
for(BitCnt=0;BitCnt<8;BitCnt++) //要传送的数据长度为8位
{
if((data<<BitCnt)&0x80)
SDA_1 //判断发送位
else
SDA_0
_Nop(15);
SCL_1 //置时钟线为高,通知被控器开始接收数据位
_Nop(15);
SCL_0
}
_Nop(15);
SDA_1 //8位发送完后释放数据线,准备接收应答位
_Nop(15);
SCL_1
_Nop(15);
if(bit_is_set(I2C_PIN,SDA))ack=0;
else ack=1; //判断是否接收到应答信号
SCL_0
_Nop(15);
}
//*****************************************************************
//函 数 名 : Stop_I2c
//建 立 时 间 : 2004-2-17
//功 能 描 述 : 从I2c总线接收1个字节的数据/命令
//备 注 : 返回接收到的数据/命令
//最后修改时间 : 2004-2-18
//*****************************************************************
u08 I2c_Rev_Byte(void)
{
u08 retc;
u08 BitCnt;
retc=0;
SDA_1 //置数据线为输入方式
for(BitCnt=0;BitCnt<8;BitCnt++)
{
_Nop(15);
SCL_0 //置时钟线为低,准备接收数据位
_Nop(20);
SCL_1 //置时钟线为高使数据线上数据有效
_Nop(20);
retc=retc<<1;
if(bit_is_set(I2C_PIN,SDA))retc=retc+1; //读数据位,接收的数据位放入retc中
_Nop(20);
}
SCL_0
_Nop(20);
return(retc);
}
//*****************************************************************
//函 数 名 : Ack_I2c
//建 立 时 间 : 2004-2-17
//功 能 描 述 : 主机的发送应答信号
//备 注 : 没有返回值
//最后修改时间 : 2004-2-17
//*****************************************************************
void Ack_I2c(u08 a)
{
if(a==0)SDA_0 //在此发出应答或非应答信号
else SDA_1
_Nop(5);
SCL_1
_Nop(5);
SCL_0 //清时钟线,钳住I2C总线以便继续接收
_Nop(5);
}
//*****************************************************************
//函 数 名 : I2c_Read
//建 立 时 间 : 2004-2-18
//功 能 描 述 : 从I2C总线上读取数据/命令,icadder是从器件地址,adder
// 是从器件的寄存器(如果有的话),count是一次读取的的数量
// *buff读取的数据存放地址
//备 注 : 没有返回值
//最后修改时间 : 2004-2-18
//*****************************************************************
void I2c_Read(u08 icadder, u08 adder, u08 count, u08 *buff)
{
u08 i;
Start_I2c();
_Nop(5);
I2c_Send_Byte(icadder); //写入IC的地址
_Nop(10);
I2c_Send_Byte(adder); //写入寄存器地址
_Nop(10);
Stop_I2c(); //可查看I2C标准
_Nop(5);
Start_I2c();
_Nop(5);
I2c_Send_Byte(icadder+1);
_Nop(10);
for (i=0;i<count;i++)
{
*buff=I2c_Rev_Byte();
if (i!=count-1) Ack_I2c(0);//除最后一个字节外,其他都要从MASTER发应答。
buff++;
}
//SendAck();//除最后一个字节外,其他都要从MASTER发应答。
Ack_I2c(1);
Stop_I2c();
}
//*****************************************************************
//函 数 名 : I2c_Send
//建 立 时 间 : 2004-2-18
//功 能 描 述 : 从I2C总线上读取数据/命令,icadder是从器件地址,adder
// 是从器件的寄存器(如果有的话),value要写入的值
//备 注 : 有返回值
//最后修改时间 : 2004-2-18
//*****************************************************************
u08 I2c_Send(u08 icadder, u08 adder, u08 value)
{
if (adder >0x17)
return False;
Start_I2c();
I2c_Send_Byte(icadder); //写入IC地址
_Nop(15);
I2c_Send_Byte(adder); //写入寄存器地址
_Nop(15);
I2c_Send_Byte(value); //写入值
_Nop(30);
Stop_I2c();
return True;
}
//==============================================
//ZLG7290接口部分
//==============================================
//*****************************************************************
//函 数 名 : ZLG_Get_Key
//建 立 时 间 : 2004-2-18
//功 能 描 述 : 从ZLG7290里读取键盘数值
//备 注 : 有返回值,返回的为读取的按键值,如果是0则是没有按键读回
//最后修改时间 : 2004-2-19
//*****************************************************************
u08 ZLG_Get_Key(void)
{
u08 tmp;
tmp = 0;
I2c_Read(zlg7290, 0x01, 0x01, &tmp);
_Nop(1);
return tmp;
}
//*****************************************************************
//函 数 名 : ZLG_Disp_Cnt
//建 立 时 间 : 2004-2-18
//功 能 描 述 : 向ZLG7290写入要显示的数码管的数量(0--7)
//备 注 : 有返回值,成功写入数据返回True,注意ZLG7290扫描位数寄存器的设置
//最后修改时间 : 2004-2-19
//*****************************************************************
u08 ZLG_Disp_Cnt(u08 Count)
{
u08 tmp;
tmp = 0;
if (Count > 0x07)
return False;
I2c_Send(zlg7290,0x0D,Count);
_Nop(1);
I2c_Read(zlg7290,0x0D,0x01,&tmp);
asm("nop");
if (tmp == Count)
return True;
else
return False;
}
//*****************************************************************
//函 数 名 : ZLG_Disp_LED
//建 立 时 间 : 2004-2-18
//功 能 描 述 : 向ZLG7290写入要显示的数码管和内容.
//备 注 : 有返回值,成功写入数据返回True,注意ZLG7290扫描位数寄存器的设置
//最后修改时间 : 2004-2-19
//*****************************************************************
u08 ZLG_Disp_LED(u08 Led_Index,u08 Led_Num)
{
u08 tmp;
tmp = 0;
if ((Led_Index < 0x10) || (Led_Index > 0x17))
return False;
I2c_Send(zlg7290,Led_Index,Led_Num);
asm("nop");
I2c_Read(zlg7290,Led_Index,0x01,&tmp);
asm("nop");
if (tmp == Led_Num)
return True;
else
return False;
}
//*****************************************************************
//函 数 名 : ZLG_Cls
//建 立 时 间 : 2004-2-18
//功 能 描 述 : 清LED显示,Type =0 全部清除显示为0,Type=1 全部不显示,默认为1
//备 注 : 有返回值,成功则返回True,失败返回False
//最后修改时间 : 2004-2-18
//*****************************************************************
u08 ZLG_Cls(u08 Type)
{
u08 tmp,i;
u08 Num;
tmp = 0;
Num = 0x00;
if (Type == 0x00)
Num = 0xFC;
for(i=0;i<8;i++)
{
I2c_Send(zlg7290,SubDpRam+i,Num);
asm("nop");
asm("nop");
}
_Nop(1);
for(i=0;i<8;i++)
{
I2c_Read(zlg7290,SubDpRam+i,0x01,&tmp);
if(tmp != Num)
return False;
}
_Nop(1);
return True;
}
#ifndef USE_INT
//*****************************************************************
//函 数 名 : ZLG_Check_Key
//建 立 时 间 : 2004-2-19
//功 能 描 述 : 检查是否有按键,只有在没有定义过USE_INT后才能使用
//备 注 : 有返回值 ,如果返回True表示有按键产生
//最后修改时间 : 2004-2-19
//*****************************************************************
u08 ZLG_Check_Key(void)
{
u08 tmp;
I2c_Read(zlg7290,0x00,0x01,&tmp);
if ((tmp & 0x01) == 0x01 )
return True;
else
return False;
}
#endif
//*****************************************************************
//函 数 名 : ZLG_Read_Reg
//建 立 时 间 : 2004-2-19
//功 能 描 述 : 读取指定寄存器,作为I2c的读取数据的API使用,扩展功能用
//备 注 : 有返回值
//最后修改时间 : 2004-2-19
//*****************************************************************
u08 ZLG_Read_Reg(u08 reg)
{
u08 tmp;
tmp = 0;
I2c_Read(zlg7290,reg,0x01,&tmp);
return tmp;
}
//*****************************************************************
//函 数 名 : ZLG_Write_reg
//建 立 时 间 : 2004-2-19
//功 能 描 述 : 向指定寄存器写入数据,作为I2c的写入数据的API使用,扩展功能用
//备 注 : 有返回值
//最后修改时间 : 2004-2-19
//*****************************************************************
u08 ZLG_Write_reg(u08 reg, u08 value)
{
u08 tmp;
tmp = 0;
I2c_Send(zlg7290,reg,value);
_Nop(1);
I2c_Read(zlg7290,reg,0x01,&tmp);
if (tmp == value)
return True;
else
return False;
}
//*****************************************************************
//函 数 名 : RST_ZLG
//建 立 时 间 : 2004-2-19
//功 能 描 述 : 由于ZLG的不稳定,控制它的复位,达到整个系统的健壮
//备 注 : 有返回值,此函数未经实际测试
//最后修改时间 : 2004-2-19
//*****************************************************************
#ifdef USE_RST
void delay(u16 dly_Time)
{
u16 i,t;
t = dly_Time;
while(t--)
for(i=0;i<6300;i++);
}
u08 RST_ZLG(void)
{
u08 tmp;
tmp = 0x00;
RST_0;
delay(400); //延时100未经实际测试
_Nop(2);
RST_1;
I2c_Send(zlg7290,0x00,0xF0);
_Nop(10);
I2c_Read(zlg7290,0x00,0x01,&tmp);
if(tmp == 0xF0)
return True;
else
return False;
}
#endif
//##################程序结束 |
|