完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
我用STM32F103做主I2C,用PCF8563做从I2C,用模拟I2C进行的通信,但是主给从发送了数据之后,接收的到都是NACK信号,为什么接收不到ACK呢?代码如下
#include "stm32f10x.h" #include "stm32f10x_i2c.h" #include "stm32f10x_gpio.h" #include "i2c_mgr.h" #include "stm32f10x_it.h" #include "rtc_mgr.h" #include "timer_mgr.h" void I2C_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; I2C_InitTypeDef I2C_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //------------RTC_SDA->PB_11RTC_SCL->PB_10---------------------------------------- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;//¿ªÂ©Êä³ö GPIO_Init(GPIOB,&GPIO_InitStructure); GPIO_SetBits(GPIOB,GPIO_Pin_11|GPIO_Pin_10); } void I2C_START(void) { SDA_OUT(); SCL_H(); SDA_H(); delay_us(5); SDA_L(); delay_us(5); } void I2C_Send_Byte(u8 txd) { u8 t; SDA_OUT(); for(t=0;t<8;t++) { SCL_L(); delay_us(1); if((txd&0x80)>>7) { SDA_H(); SCL_H(); delay_us(5); txd<<=1; } else { SDA_L(); SCL_H(); delay_us(5); txd<<=1; } } SCL_L(); } void I2C_STOP(void) { SDA_OUT(); SCL_L(); delay_us(5); SDA_L(); delay_us(5); SCL_H(); delay_us(5); SDA_H(); delay_us(5); } u8 I2C_Wait_ACK(void) { u8 waitcnt = 0; u8 slaveack = 0; SCL_L(); SDA_IN(); //delay_us(5); SCL_H(); delay_us(5); if(READ_SDA()) { SCL_L(); return 1; } SCL_L(); delay_us(5); return 0; } void I2C_ACK(void) { SCL_L(); SDA_OUT(); SDA_L(); delay_us(5); SCL_H(); delay_us(5); SCL_L(); } void I2C_NACK(void) { SCL_L(); SDA_OUT(); SDA_H(); delay_us(5); SCL_H(); delay_us(5); SCL_L(); } u8 I2C_Read_Byte(unsigned char ack) { unsigned char i,receive=0; SDA_IN(); for(i=0;i<8;i++ ) { SCL_H(); delay_us(5); receive<<=1; if(READ_SDA())receive++; delay_us(5); SCL_L(); delay_us(5); } if (!ack) I2C_NACK(); else I2C_ACK(); return receive; } void I2C_Write(u8 WriteAddr,u8 Dat) { I2C_START(); I2C_Send_Byte(PCF8563_ADDR_W); I2C_Wait_ACK(); I2C_Send_Byte(WriteAddr); I2C_Wait_ACK(); I2C_Send_Byte(Dat); I2C_Wait_ACK(); I2C_STOP(); } u8 I2C_Read(u8 ReadAddr) { u8 ReData,t=0; I2C_START( ); I2C_Send_Byte(PCF8563_ADDR_W); I2C_Wait_ACK(); I2C_Send_Byte(ReadAddr); I2C_Wait_ACK(); I2C_START(); I2C_Send_Byte(PCF8563_ADDR_R); I2C_Wait_ACK(); ReData = I2C_Read_Byte(0); I2C_STOP(); return ReData; } |
|
相关推荐
35个回答
|
|
/*
* 函数名: static void I2C_Stop(void) * 描述 : 终止信号 * 输入 : 无 * 输出 : 无 * 说明 : */ static void I2C_Stop(void) { SCL_L; I2C_delay(); SDA_L; I2C_delay(); SCL_H; I2C_delay(); SDA_H; I2C_delay(); } |
|
|
|
可是不对啊,I2C的时序不是发从设备地址等ACK,发寄存器地址等ACK,发要写入的数据等ACK,最后发STOP信号吗?您是想让我在每一个等ACK前都发一个STOP信号吗? |
|
|
|
我是说每次完整的通讯完成后。
|
|
|
|
|
|
|
|
|
|
|
|
我调试半天IIC死活不通,后来发现板子引脚反了
|
|
|
|
|
|
|
|
结贴:
I2C通信,首先肯定STM32F103要进行I2C通信,这要设置SDA的方向; 其次,之所以一直接收到NACK ,说明从设备没有收到有效的地址,可是主设备发送没有错,于是用示波器测了从设备的电压,和时钟,发现晶振有问题,竞争给的不正常 |
|
|
|
本帖最后由 stm1024 于 2018-3-28 18:09 编辑
你的STM32在作为主机发送数据到IIC总线上时,配置为输出模式,这个OK,但是需要从PCF8563中得到应答,相当于是要从总线上读取数据,这个时候GPIO应该配置为输入模式,但似乎并没有看到类似的语句或代码,SDA_IN吗?也不太清楚具体代码如何,所以不好判断。 |
|
|
|
|
|
|
|
60user36 发表于 2018-12-24 13:53 是的,有方向改变的语句 |
|
|
|
|
|
看一下从设备地址是否正确,可能是主发送的地址和从设备地址不匹配,所以从不响应
|
|
|
|
for(t=0;t<8;t++) { IIC_SDA=(txd&0x80)>>7; txd<<=1; delay_us(2); IIC_SCL=1; delay_us(2); IIC_SCL=0; delay_us(2); } (txd&0x80)>>7是为了取txd的最高位, txd<<=1; 是将下一位数据移位到最高位,就可以(txd&0x80)>>7取走最高位 |
|
|
|
60user36 发表于 2018-12-24 13:53 设置方向的确是SDA_IN #define SDA_IN() {GPIOB->MODER&=~(3<<(7*2));GPIOB->MODER|=0<<7*2;} #define SDA_OUT() {GPIOB->MODER&=~(3<<(7*2));GPIOB->MODER|=1<<7*2;} |
|
|
|
不错,很好的经验分享,辛苦麻烦了,欠缺这方面的资料,非常感谢。
|
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
2105 浏览 1 评论
AD7686芯片不传输数据给STM32,但是手按住就会有数据。
1941 浏览 3 评论
4537 浏览 0 评论
如何解决MPU-9250与STM32通讯时,出现HAL_ERROR = 0x01U
2084 浏览 1 评论
hal库中i2c卡死在HAL_I2C_Master_Transmit
2599 浏览 1 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-23 03:50 , Processed in 0.958141 second(s), Total 73, Slave 66 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号