急问:马老师,能不能帮忙看16模拟I2C的程序,不能读,数码管显示的是2,都调了一周了
硬件电路是PA0 PA1接AT24C02的SDA SCL程序:
#include <iom16v.h>
#include <stdio.h>
#include <macros.h>
#include <string.h>
#pragma data:data
//#include "pcf8563.h"
//#include "lcd.h"
//#include "keyboard.h"
unsigned char table[] = { 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
unsigned char WriteDeviceAddress=0xa0; //写命令数//const
unsigned char ReadDviceAddress=0xa1; //读
unsigned char Data;
#pragma data:code
//时钟芯片数据接口PA0
#define DATE_DT_set asm("sbi 0x1B,0")
#define DATE_DT_clr asm("cbi 0x1B,0")
//时钟芯片时钟接口PA1
#define DATE_CLK_set asm("sbi 0x1B,1")
#define DATE_CLK_clr asm("cbi 0x1B,1")
void delayus(unsigned char i)
{int j;
while(i)
{
for(j=11000;j>0;j--)
;
i--;
}
}
///////////////////////////////////////////////////
void IO_init(void)
{
DDRD=0XFF;
DDRB=0XFF;
PORTD=0XFF;
PORTB=0XFF;
//DDRD=0XFF;
}
/////////////////////////////////////////////////
display(int temp)
{
PORTD=0X00;
PORTB=table;
}
// ************************************************ //
// *** This routine will send the I2C Start Bit *** //
// ************************************************ //
void I2C_Start (void) //I2C发送开始位
{
DDRA|=0x03; //将PA0数据端口(SDA),PA1时钟端口(SCL)设为输出
DATE_CLK_set; //将时钟端口(SCL)设为高
DATE_DT_set; //将数据端口(SDA)设为高
delayus(5);
DATE_DT_clr; //将数据端口(SDA)设为低
delayus(10);
//DATE_DT_set;
}
// *********************************************** //
// *** This routine will send the I2C Stop Bit *** //
// *********************************************** //
void I2C_Stop (void) //I2C发送停止位
{
DDRA|=0x03; //将PA0数据端口(SDA),PA1时钟端口(SCL)设为输出
DATE_DT_clr; //将数据端口(SDA)设为低
DATE_CLK_set; //将时钟端口(SCL)设为高
delayus(10);
DATE_DT_set; //将数据端口(SDA)设为高
delayus(2);
}
// *********************************************************************** //
// *** 发送完毕检查校验位,有校验位返回1,无返回0 *** //
// *********************************************************************** //
unsigned char I2C_Ackn(void)
{
unsigned char errtime=255;
//DATE_CLK_clr; // 将时钟端口(SCL)设为低
DATE_CLK_set;
//DDRA&=0x00;
DDRA|=0xFE; // 设置数据口(SDA)为输入
// DDRA&=0xfe;
delayus(5);
while(PINA&0x01)
{
errtime--;
if (!errtime) //errtime=0,没接收到
{
I2C_Stop();
return 0;
}
}
// DDRA|=0x03;
//DATE_DT_clr;
//DATE_CLK_set;
//delayus(2);
DATE_CLK_clr; // 将时钟端口(SCL)设为低
delayus(2);
DATE_CLK_set;
delayus(2);
return 0x01; //true
}
// ******************************************************** //
// *** This routine will write a byte to the I2C device *** //
// ******************************************************** //
void Write_I2C_Byte(unsigned char byte) //写一个字节到I2C设备
{
unsigned char i;
DDRA|=0x03; //将PA0数据端口(SDA)设为输出
for (i = 0; i < 8; i++) //传送8位数据
{
DATE_CLK_clr; //将时钟端口(SCL)设为低
if((byte & 0x80)) DATE_DT_set; // 设置 SDA 位
else DATE_DT_clr; // 清除 SDA 位
delayus(2);
DATE_CLK_set; //将时钟端口(SCL)设为高
asm("nop");
byte = byte << 1; //将输出数据左移一位
}
// DATE_CLK_clr; // 校验标志位 (每传送8位,有一校验位)
//if (I2C_Ackn()==0) // Check for acknowledge from I2C device
//yonghudenglu();
//DATE_CLK_clr;
DATE_CLK_set;
}
// ********************************************************* //
// *** This routine will read a byte from the I2C device *** //
// ********************************************************* //
unsigned char Read_I2C_Byte(void) //读取I2C设备的数据
{
unsigned char i,buff = 0;
delayus(2);
DDRA|=0x02; //PA1为时钟,输出
DDRA&=0xfe; //设置数据口(SDA)为输入
for (i = 0; i < 8; i++)
{
DATE_CLK_clr; // 将时钟端口(SCL)设为低
delayus(2);
// DATE_CLK_set; //将时钟端口(SCL)设为高
// delayus(2);
// 在 SDA 位上读取数据
if ( PINA&=0x01 )
buff++;
buff = (buff << 1);
delayus(2);
DATE_CLK_set; //将时钟端口(SCL)设为高
delayus(2);
}
DDRA|=0x03; //设为输出,发送校验位
DATE_DT_clr;
delayus(2);
DATE_CLK_set;
delayus(2);
DATE_CLK_clr; //将时钟端口(SCL)设为高
DATE_DT_clr;
return buff; // 返回读取值
}
///////////////////////////////////
void main()
{ Data=2;
IO_init();
delayus(20);
while(1)
{
I2C_Start();
Write_I2C_Byte(0xa0);
while(I2C_Ackn()==0)
{display(1);}
Write_I2C_Byte(0x04); //写入的字地址
while(I2C_Ackn()==0)
{display(9);}
Write_I2C_Byte(4); //写入的字地址的数据
while(I2C_Ackn()==0)
{display(5);}
I2C_Stop ();
delayus(2000);
////////////////////
I2C_Start();
Write_I2C_Byte(0xa0);
while(I2C_Ackn()==0)
{display(4);}
Write_I2C_Byte(0x04); //定位字地址
while(I2C_Ackn()==0)
{display(7);}
I2C_Stop ();
/////////////////////////
I2C_Start();
delayus(2);
Write_I2C_Byte(0xa1); //定位字地址
while(I2C_Ackn()==0)
{display(2);}
Data= Read_I2C_Byte();
I2C_Stop ();
display(Data);
}
}
我的邮箱是youjiandong012@163.com. 用CVAVR吧,使用它的I2C模拟接口函数,1个小时搞定了。
页:
[1]