|
小弟现在在做一个用AVR单片机用PCA9555的I2C接口来扩展I/O的实验,可是我就是通不起来,搞了好几次了还没能有结果,我想论坛里面谁又这个经验能帮小弟一把,指点一下,小弟不胜感激,下面是我的程序,麻烦帮忙看一下
#include <iom16v.h>
#include <macros.h>
#include <delay.h>
#include "I2Ctest.h"
/* I2C 通信错误标志,默认为0,出错时为1*/
unsigned char g_ucErrFlg[8] = {0};
/*清除中断标志位,使能TWI功能,开放TWI中断,在主控接收状态下不对SDA线作应答*/
#define Twi_NoAcK() {TWCR=TWCR&TWCR_CMD_MASK|(1<<TWINT);}
void twi_master_init(void)
{
TWCR= 0x00; /*disable twi*/
TWBR= 0x64; /*set bit rate = 100,实际SCL 频率=37K*/
TWSR= 0x00; /*set prescale=1*/
TWAR= 0x00; /*set slave address*/
TWCR= (1<<TWEN); /*enable twi*/
}
/*操作步骤: 启动,发送地址,发送数据,关闭总线*/
char i2c_maste_transt(unsigned char addr, unsigned char data0,unsigned char data1,unsigned char comdata)
{
if(OK != i2c_start())
{
return ERROR;
}
if(i2c_write_addr(addr, TW_WRITE) == TW_MT_SLA_ACK) /*发送地址成功并收到ACK*/
{
if(i2c_write_command(comdata) == OK)
{
if(i2c_write_data(data0) == OK);
{
i2c_write_data(data1);
}
}
}
i2c_stop();
}
/*发送控制数据,控制pca9555是还是写,是哪个IO口*/
char i2c_write_command(unsigned char comdata)
{
unsigned int iCnt = 0;
TWDR = comdata; /*写如控制寄存器*/
TWCR = (1<<TWINT)|(1<<TWEN);
while (!(TWCR & (1<<TWINT)))
{
_NOP();
if (iCnt++ > 100)
{
g_ucErrFlg[1]++;
return ERROR;
}
}
/*TWSR高五位为I2C工作状态。*/
if ((TWSR & 0xF8) != TW_MT_SLA_ACK)
{
return ERROR;
}
return OK;
}
/*总线上起动开始条件*/
char i2c_start(void)
{
unsigned int iCnt = 0;
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
while (!(TWCR & (1<<TWINT))) /*等待START 信号成功发送*/
{
if (iCnt++ > 10)
{
g_ucErrFlg[0]++;
return ERROR;
}
}
if ((TWSR & 0xF8) != TW_START)
{
return ERROR;
}
return OK;
}
/*发送地址,r_w:1为读,0为写*/
unsigned char i2c_write_addr(unsigned char addr,unsigned char r_w)
{
unsigned int iCnt = 0;
if(TW_READ == r_w)
{
TWDR = addr | r_w; /*RW 为1:读操作*/
}
else
{
TWDR = addr & 0xFE; /*RW 为0: 写操作*/
}
TWCR = (1<<TWINT)|(1<<TWEN);
while (!(TWCR & (1<<TWINT)))
{
_NOP();
if (iCnt++ > 100)
{
g_ucErrFlg[1]++;
return ERROR;
}
}
/*TWSR高五位为I2C工作状态。*/
if ((TWSR & 0xF8) != TW_MT_SLA_ACK)
{
return ERROR;
}
return(OK);
}
/*发送数据*/
unsigned char i2c_write_data(unsigned char data)
{
unsigned int iCnt = 0;
TWDR = data;
TWCR = (1<<TWINT)|(1<<TWEN);
while (!(TWCR & (1<<TWINT)))
{
_NOP();
if (iCnt++ > 100)
{
g_ucErrFlg[2]++;
return ERROR;
}
}
/*TWSR高五位为I2C工作状态。*/
if ((TWSR & 0xF8) != TW_MT_DATA_ACK)
{
return ERROR;
}
return OK;
}
/*总线上起动停止条件 */
void i2c_stop(void)
{
TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN);
return;
}
/*操作步骤,启动,发送地址,读数据,关闭总线*/
unsigned char i2c_maste_read(unsigned char addr)
{
unsigned char tmp=0;
i2c_start();
if(i2c_write_addr(addr, 1)==TW_MR_SLA_ACK) /*发送地址成功并收到ACK*/
{
tmp=i2c_read();
}
i2c_stop();
return tmp;
}
/*从器件读出一个字节*/
unsigned char i2c_read(void)
{
unsigned int iCnt = 0;
TWCR = (1<<TWINT)|(1<<TWEN);
Twi_NoAcK();
while (!(TWCR & (1<<TWINT)))
{
_NOP();
if (iCnt++ > 100)
{
g_ucErrFlg[3]++;
return ERROR;
}
}
return(TWDR);
}
void main(void)
{
unsigned char i=0,tmp=0;
/*re-enable interrupts*/
DDRC=0X00;
PORTC=0x03; /*使能内部上拉电阻*/
twi_master_init();
while(1)
{
DDRD = 0XFF;
PORTD = 0x00;
i2c_maste_transt(0x4e,0x02,0x01,0x02);
i++;
delay(10);
DDRD = 0XFF;
PORTD = 0xff;
tmp=i2c_maste_read(0x4f); /*读一个数*/
delay(10);
DDRA = 0XFF;
PORTA = tmp;
if(tmp==0x10)
{
i=0;
}
}
}
有哪里错误的希望能够直接指出或者帮我改一下,谢谢! |
阿莫论坛20周年了!感谢大家的支持与爱护!!
你熬了10碗粥,别人一桶水倒进去,淘走90碗,剩下10碗给你,你看似没亏,其实你那10碗已经没有之前的裹腹了,人家的一桶水换90碗,继续卖。说白了,通货膨胀就是,你的钱是挣来的,他的钱是印来的,掺和在一起,你的钱就贬值了。
|