完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
你写和读的时间间隔长一点 是不是时序乱了
|
|
|
|
|
|
|
|
这是gpio模拟的iic还是硬件IIC?
|
|
|
|
|
|
|
|
有示波器就好办了 你看看 收到0XFF的时候 读和写的地址对不对 还有看看应答 |
|
|
|
模拟端口IIC,还是003内设的IIC
|
|
|
|
003的内部外设寄存器,读出的时候,需要清掉寄存器的缓冲数据,还有可能是应答位接收不到造成的问题
|
|
|
|
|
|
|
|
这个缓冲区需要怎么清呢? |
|
|
|
|
|
|
|
看到的波形,第一次读应答不对 |
|
|
|
|
|
|
|
I2C_DR数据寄存器,I2C_TRISE上升时间寄存器,这两个看下有没有配对,还有就是模拟I2C跟硬件的I2C终究是有点区别的,如果不行的话,不用硬件的I2C,把两个端口做成模拟电平通信就OK了
|
|
|
|
嗯,我再查查,但是不明白的是连续读两次,第二次就正确 |
|
|
|
SXST_T 发表于 2017-3-15 09:04 嗯,我再调试一下 |
|
|
|
|
|
|
|
//*******************硬件IIC从测试程序******************/
#include "stm8s.h" #define SLAVE_ADDRESS 0xA0 void main(void) { /* system_clock / 1 */ CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1); I2C_DeInit(); /* Initialize I2C peripheral */ I2C_StretchClockCmd(DISABLE); I2C_Init(100000, SLAVE_ADDRESS, I2C_DUTYCYCLE_16_9, I2C_ACK_CURR, I2C_ADDMODE_7BIT, 16); /* Enable Error Interrupt*/ I2C_ITConfig((I2C_IT_TypeDef)(I2C_IT_ERR | I2C_IT_EVT | I2C_IT_BUF), ENABLE); /* Enable general interrupts */ enableInterrupts(); /*Main Loop */ while (1) { /* infinite loop */ } } /------------------------------------------------------------------------------------ 下面是中断函数 ------------------------------------------------------------------------------------/ unsigned char Slave_Buffer_Rx[10]; INTERRUPT_HANDLER(I2C_IRQHandler, 19) { static unsigned char reg_slave = 0; static unsigned char rx_count = 0; /* Read SR2 register to get I2C error */ if ((I2C->SR2) != 0) { /* Clears SR2 register */ I2C->SR2 = 0; } Event = I2C_GetLastEvent(); switch (Event) { /******* Slave transmitter ******/ /* check on EV1 */ case I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED: break; /* check on EV3 */ case I2C_EVENT_SLAVE_BYTE_TRANSMITTING: /* Transmit data */ I2C_SendData(Slave_Buffer_Rx[reg_slave]); break; /******* Slave receiver **********/ /* check on EV1*/ case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED: rx_count = 1; break; /* Check on EV2*/ case I2C_EVENT_SLAVE_BYTE_RECEIVED: if(rx_count == 1) { reg_slave = I2C_ReceiveData(); rx_count = 2; } else if(rx_count == 2) { Slave_Buffer_Rx[reg_slave] = I2C_ReceiveData(); rx_count = 0; } break; /* Check on EV4 */ case (I2C_EVENT_SLAVE_STOP_DETECTED): /* write to CR2 to clear STOPF flag */ I2C->CR2 |= I2C_CR2_ACK; break; default: break; } } //*******************硬件IIC主测试程序******************// #include "stm8s.h" #define EEPROM_ADDRESS 0xA0 #define Fsys 16000000 void Delay_ms(unsigned int mm) { unsigned int mm2,mm1=Fsys/6000; while(mm--) for(mm2=mm1;mm2>0;mm2--); } void I2C_Config(void) { I2C_DeInit(); I2C_Init(100000, 0xB0, I2C_DUTYCYCLE_16_9, I2C_ACK_CURR, I2C_ADDMODE_7BIT, 16); CLK_PeripheralClockConfig(CLK_PERIPHERAL_I2C, ENABLE); I2C_Cmd(ENABLE); } /******************************************************************************* * 名称: I2C_EEPROM_WriteOneByte * 功能: I2C主模式往I2C从器件内部地址写一个字节 * 形参: WriteAddr Byte * 返回: 无 * 说明: */ void I2C_WriteOneByte(u8 WriteAddr,u8 Byte) { /* 等待空闲 */ //while(I2C_GetFlagStatus(I2C_FLAG_BUSBUSY)); while((I2C->SR3 & 0x02 ) != 0); /* 发起始位 */ //I2C_GenerateSTART(ENABLE); I2C->CR2 |= 0x01; /* 测试EV5 ,检测从器件返回一个应答信号*/ while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT)); /* 设置I2C从器件地址,I2C主设备为写模式*/ I2C_Send7bitAddress(EEPROM_ADDRESS, I2C_DIRECTION_TX); /* 测试EV6并清除标志位,检测从器件返回一个应答信号 */ while(!I2C_CheckEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); /* 设置往从器件写数据内部的地址 */ //I2C_SendData(WriteAddr); I2C->DR = WriteAddr; /* 测试EV8并清除标志位 ,检测从器件返回一个应答信号*/ while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTING)); /* 向从器件写一个字节 */ //I2C_SendData(Byte); I2C->DR = Byte; /* 测试EV8_2并清除标志位,检测从器件返回一个应答信号 */ while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED)); /* 发结束位 */ //I2C_GenerateSTOP(ENABLE); I2C->CR2 |= 0x02; } /************************************************************************* * 名称: I2C_EEPROM_ReadOneByte * 功能: 从从设备读取一个字节 * 形参: ReadAddr * 返回: 字节数据 * 说明: 无 */ u8 I2C_ReadOneByte(u8 ReadAddr) { u8 RxData; /* 等待空闲 */ //while(I2C_GetFlagStatus(I2C_FLAG_BUSBUSY)); while((I2C->SR3 & 0x02 ) != 0); /* 发起始位 */ //I2C_GenerateSTART(ENABLE); I2C->CR2 |= 0x01; /* 测试EV5 ,检测从器件返回一个应答信号*/ while (!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT)); /* 设置I2C从器件地址,I2C主设备为写模式*/ I2C_Send7bitAddress(EEPROM_ADDRESS , I2C_DIRECTION_TX); /* 测试EV6并清除标志位 */ while (!I2C_CheckEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); //I2C_SendData(ReadAddr); I2C->DR = ReadAddr; /* 测试EV8并清除标志位 */ while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED)); /* 发起始位 */ //I2C_GenerateSTART(ENABLE); I2C->CR2 |= 0x01; /* 测试EV5 ,检测从器件返回一个应答信号*/ while (!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT)); /* 设置I2C从器件地址,I2C主设备为读模式*/ I2C_Send7bitAddress(EEPROM_ADDRESS, I2C_DIRECTION_RX); /* 测试EV6 ,检测从器件返回一个应答信号*/ while (!I2C_CheckEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); //I2C_AcknowledgeConfig(I2C_ACK_NONE);//不使能应答 I2C->CR2 &= 0xfb; /* 测试EV7,等待数据接收完毕 */ while(!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_RECEIVED)); //RxData=I2C_ReceiveData(); RxData = ((uint8_t)I2C->DR); /* 发结束位*/ //I2C_GenerateSTOP(ENABLE); I2C->CR2 |= 0x02; return RxData; } void main(void) { unsigned char read_data; /*配置内部16MHz时钟------------------------------*/ CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1); I2C_Config(); while(1) { I2C_WriteOneByte(5,0x11); read_data = I2C_ReadOneByte(5); Delay_ms(100); } } |
|
|
|
SXST_T 发表于 2017-3-15 09:04 大神,帮我看一下硬件IIC主从程序,不知道是不是哪个标志没有清,还是不行的,多谢了 |
|
|
|
在不?你的程序能给我发一份不?我现在调试从机的话,只能接收一个字节,如果想一次接收多个字节的话,在完成第一个字节的接收后 SR1的STOP会置位。不知道是什么问题
|
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
使用stm32l451片子,对ad7606进行3通道100k采样值跳动问题?
135 浏览 0 评论
STM32进行DMA数据转运,为什么只有A组最后一位数据被转运到B组去?
1337 浏览 2 评论
1650 浏览 3 评论
1258 浏览 0 评论
嵌入式开发 Win11安装ST-Link 提示 设备描述符请求失败 怎么处理?
1391 浏览 0 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-8-19 20:23 , Processed in 0.932716 second(s), Total 111, Slave 91 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号