想请教PCA9555的用法,不知道坛子里面有没有用过的人。
小弟现在在做一个用AVR单片机用PCA9555的I2C接口来扩展I/O的实验,可是我就是通不起来,搞了好几次了还没能有结果,我想论坛里面谁又这个经验能帮小弟一把,指点一下,小弟不胜感激,下面是我的程序,麻烦帮忙看一下#include <iom16v.h>
#include <macros.h>
#include <delay.h>
#include "I2Ctest.h"
/* I2C 通信错误标志,默认为0,出错时为1*/
unsigned char g_ucErrFlg = {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++;
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++;
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++;
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++;
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++;
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;
}
}
}
有哪里错误的希望能够直接指出或者帮我改一下,谢谢! 为什么没人回答我啊,难道都没人用过,用过的告诉我下啊 zjm19860703 发表于 2008-8-19 12:06 static/image/common/back.gif
为什么没人回答我啊,难道都没人用过,用过的告诉我下啊
楼主,程序调通了吗? PCA9555简单的狠,做过1个项目,扩展32个输入,16个输出 yuyu87 发表于 2013-6-25 16:22 static/image/common/back.gif
PCA9555简单的狠,做过1个项目,扩展32个输入,16个输出
想问问,9555的用法。是不是当主控设定好了16个IO的输入输出后,如果这16个IO中有一个改变,就会产生中断,主控接收到中断之后就通过IIC去读这16个IO现在的状态,从而知道是哪一个键按下了? 是这样的,有任意按键变化就会触发中断脚,然后主机读取IIC,就知道哪个有输入了,
我读取的是气缸传感器,没有读取它的中断脚,是定时读取,每隔10ms读取一次 yuyu87 发表于 2013-6-27 13:46
是这样的,有任意按键变化就会触发中断脚,然后主机读取IIC,就知道哪个有输入了,
我读取的是气缸传感器 ...
最近在写PCA9555的驱动,但是没弄好。想问下配置成输出口的话,配置寄存器已经配置好了作为输出口,那么直接往Output register寄存器对应的位写“1”就输出为高电平吗? 图图2014 发表于 2015-11-19 22:34
最近在写PCA9555的驱动,但是没弄好。想问下配置成输出口的话,配置寄存器已经配置好了作为输出口,那么 ...
是的,写1为高电平
图图2014 发表于 2015-11-19 22:34
最近在写PCA9555的驱动,但是没弄好。想问下配置成输出口的话,配置寄存器已经配置好了作为输出口,那么 ...
认真看下手册吧,很简单的 PCA9555多少钱? yuyu87 发表于 2015-11-20 08:58
认真看下手册吧,很简单的
搞了两天了,也没弄出来啊,项目急呢,麻烦您给指点下吧,这个芯片的IIC读取时可以单个寄存器的读写是吧?
例如:PCA9555_WriteReg(0x40,0x06,0xf0);//配置P0.0~P0.4为输出,P0.5~P0.7为输入
PCA9555_WriteReg(0x40,0x02,0x0f);//将输出口P0.0~P0.4置高电平
不知道这样子对不对啊,但是不出高电平啊 LVmcu 发表于 2015-11-20 09:19
PCA9555多少钱?
我也不晓得多钱,公司硬件工程师买的。去淘宝上搜一下吧,就知道了。 简单 I2C 读写 寄存器 就好,用过 这个芯片,不过这芯片 不咋的。 有时候不如数字芯片 来的直接 本帖最后由 图图2014 于 2015-11-20 17:09 编辑
dengxiaofeng 发表于 2015-11-20 10:28
简单 I2C 读写 寄存器 就好,用过 这个芯片,不过这芯片 不咋的。 有时候不如数字芯片 来的直接 ...
我把代码贴出来,大家帮我看下吧,到底是哪里出了问题。还是PCA9555这个芯片有问题,是假的之类的。
我等级不够,发不了新帖,就借这个帖子发一下吧,就麻烦大家给我看一下吧。非常感谢!
单片机是STM32F407VGT6
////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define PCA9555_WR 0x40 //PCA9555写地址
#define PCA9555_RD 0x41 //PCA9555读地址
//PC2->SCL1PC3->SDA1PCA9555 IIC I/O口定义
//这部分的IO口输入/输出电平PCout(x)没有贴出来,也都是复用别人的代码,经过验证了,而且拿这个IIC驱动,修改了IO口,去驱动QN8035,读写都没问题。
#define SDA1_IN(){GPIOC->MODER&=~(3<<(3*2));GPIOC->MODER|=0<<3*2;}
#define SDA1_OUT() {GPIOC->MODER&=~(3<<(3*2));GPIOC->MODER|=1<<3*2;}
#define IIC1_SCL PCout(2) //IIC1_SCL
#define IIC1_SDA PCout(3) //IIC1_SDA
#define READ_SDA1 PCin(3)//读取IIC1_SDA
//-------------------------------IIC1驱动-------------------------------//
/*************************************************************
//函数名称:IIC1_Start
//函数功能:IIC起始信号
//入口参数:无
//出口参数:无
**************************************************************/
void IIC1_Start(void)
{
SDA1_OUT(); //sda输出
IIC1_SDA=1;
IIC1_SCL=1;
delay_us(2);
IIC1_SDA=0; //START:when CLK is high,DATA change form high to low
delay_us(2);
IIC1_SCL=0;
}
/*************************************************************
//函数名称:IIC1_Stop
//函数功能:IIC结束信号
//入口参数:无
//出口参数:无
**************************************************************/
void IIC1_Stop(void)
{
SDA1_OUT();//sda输出
IIC1_SCL=0;
IIC1_SDA=0;//STOP:when CLK is high DATA change form low to high
delay_us(2);
IIC1_SCL=1;
IIC1_SDA=1;//发送IIC总线结束信号
delay_us(2);
}
/*************************************************************
//函数名称:IIC1_Wait_Ack
//函数功能:等待应答信号
//入口参数:无
//出口参数:1:接收应答失败,0:接收应答成功
**************************************************************/
u8 IIC1_Wait_Ack(void)
{
u8 ucErrTime=0;
SDA1_IN(); //SDA设置为输入
IIC1_SDA=1;
delay_us(1);
IIC1_SCL=1;
while(READ_SDA1)
{
ucErrTime++;
if(ucErrTime>250)//超过250次,失败
{
IIC1_Stop();
return 1;
}
}
IIC1_SCL=0;//SCL拉低
return 0; //应答成功
}
/*************************************************************
//函数名称:IIC1_Ack
//函数功能:产生应答信号
//入口参数:无
//出口参数:无
**************************************************************/
void IIC1_Ack(void)
{
IIC1_SCL=0;
SDA1_OUT();
IIC1_SDA=0;
delay_us(2);
IIC1_SCL=1;
delay_us(2);
IIC1_SCL=0;
}
/*************************************************************
//函数名称:IIC_NAck
//函数功能:不产生应答信号
//入口参数:无
//出口参数:无
**************************************************************/
void IIC1_NAck(void)
{
IIC1_SCL=0;
SDA1_OUT();
IIC1_SDA=1;
delay_us(2);
IIC1_SCL=1;
delay_us(2);
IIC1_SCL=0;
}
/*************************************************************
//函数名称:IIC_Send_Byte
//函数功能:发送1byte
//入口参数: 发送1byte数据
//出口参数:无
**************************************************************/
void IIC1_Send_Byte(u8 SendByte)
{
u8 t;
SDA1_OUT(); //SDA设置输出
IIC1_SCL=0;//拉低时钟,开始传输数据
for(t=0;t<8;t++)
{
if((SendByte&0x80)>>7)
IIC1_SDA=1;
else
IIC1_SDA=0;
SendByte<<=1;
delay_us(1);
IIC1_SCL=1;
delay_us(2);
IIC1_SCL=0;
delay_us(2);
}
}
/*************************************************************
//函数名称:IIC_Read_Byte
//函数功能:读取1byte
//入口参数: 是否要求应答,0:应答 1:不应答
//出口参数: 读到的1byte数据
**************************************************************/
u8 IIC1_Read_Byte(u8 ack)
{
u8 i;
u8 ReceiveByte=0;
SDA1_IN(); //SDA输入
for(i=0;i<8;i++)
{
IIC1_SCL=0;
delay_us(2);
IIC1_SCL=1;
ReceiveByte<<=1;
if(READ_SDA1)
ReceiveByte++;
delay_us(1);
}
// SDA_OUT(); //SDA设置输出
if (ack)
{
IIC1_NAck(); //不应答
}
else
{
IIC1_Ack();//发送ACK
}
return ReceiveByte;
}
//-------------------------------PCA9555驱动-------------------------------//
/*************************************************************
//函数名称:PCA9555_Init
//函数功能:PCA9555初始化
//入口参数: 无
//出口参数: 无
**************************************************************/
void PCA9555_Init(void)
{
//PCA9555_WriteOneByte(0x02,0xff);//所有P0输出置为高电平
//PCA9555_WriteOneByte(0x03,0xff);//所有P1输出置为高电平
//PCA9555_WriteOneByte(0x04, 0x00);//所有P0输入均不反转
//PCA9555_WriteOneByte(0x05, 0x00);//所有P1输入均不反转
PCA9555_WriteOneByte(0x06,0x7f);//配置IO口方向,P0.1/1/2/3/4/5/6输入,P0.7输出
PCA9555_WriteOneByte(0x07,0xc7);//配置IO口方向,P1.0/1/2/6/7输入,P1.3/4/5输出
delay_ms(20);
}
/*************************************************************
//函数名称:PCA9555_ReadOneByte
//函数功能:PCA9555读取1byte数据
//入口参数: 数据地址
//出口参数: 读到的1byte数据
**************************************************************/
u8 PCA9555_ReadOneByte(u8 Addr)
{
u8 temp = 0;
IIC1_Start();
IIC1_Send_Byte(PCA9555_WR); //写操作
IIC1_Wait_Ack();
IIC1_Send_Byte(Addr); //送地址
IIC1_Wait_Ack();
IIC1_Start();
IIC1_Send_Byte(PCA9555_RD); //读操作
IIC1_Wait_Ack();
temp = IIC1_Read_Byte(1);//读数据,NACK
IIC1_Stop();
return temp;
}
/*************************************************************
//函数名称:PCA9555_WriteOneByte
//函数功能:PCA9555写入1byte数据
//入口参数: 要写入的地址,数据
//出口参数: 无
**************************************************************/
void PCA9555_WriteOneByte(u8 Addr, u8 Data)
{
IIC1_Start();
IIC1_Send_Byte(PCA9555_WR);//写操作
IIC1_Wait_Ack();
IIC1_Send_Byte(Addr); //送地址
IIC1_Wait_Ack();
IIC1_Send_Byte(Data);//送数据
IIC1_Wait_Ack();
IIC1_Stop();
}
/---------------------------------------------------主函数--------------------------------------------------------------------------------/
//主函数,就是测试下PCA9555的P0.7口输出高、低电平,但是并不是我想要的结果,移植都高电平,不出低电平
int main(void)
{
RCC_Init();
delay_init(SystemClock);
GPIO_Init();
delay_ms(100);
IWDG_Feed();
PCA9555_Init();
while(1)
{
delay_ms(1000);
PCA9555_WriteOneByte(0x02,0x7f);//P0.7输出低
delay_ms(1000);
PCA9555_WriteOneByte(0x02,0x8f);//P0.7输出高
delay_ms(1000);
}
return 1;
}
图图2014 发表于 2015-11-20 17:02
我把代码贴出来,大家帮我看下吧,到底是哪里出了问题。还是PCA9555这个芯片有问题,是假的之类的。
我等 ...
上 逻辑分析仪or 示波器看波形 立马就能找到问题 图图2014 发表于 2015-11-20 10:17
我也不晓得多钱,公司硬件工程师买的。去淘宝上搜一下吧,就知道了。
PCA9555淘宝上看3-4块,还不如果个单片机来的方便。不知道你们这样选择的原因是什么?
页:
[1]