哪位大神用stm8s003做IIC的从机?
你写和读的时间间隔长一点 是不是时序乱了
时序没有乱的,下面是用示波器抓到的波形
这是gpio模拟的iic还是硬件IIC?
主是模拟,从是stm8s的硬件
有示波器就好办了 你看看 收到0XFF的时候 读和写的地址对不对 还有看看应答
模拟端口IIC,还是003内设的IIC
003的内部外设寄存器,读出的时候,需要清掉寄存器的缓冲数据,还有可能是应答位接收不到造成的问题
从用的是硬件IIC
这个缓冲区需要怎么清呢?
第一次读数据的时候应答不对
看到的波形,第一次读应答不对
应答不对 那应该就是你发的不对 要么数据不对 要么时序不对
I2C_DR数据寄存器,I2C_TRISE上升时间寄存器,这两个看下有没有配对,还有就是模拟I2C跟硬件的I2C终究是有点区别的,如果不行的话,不用硬件的I2C,把两个端口做成模拟电平通信就OK了
嗯,我再查查,但是不明白的是连续读两次,第二次就正确
嗯,我再调试一下
不错,真是太棒了!
//*******************硬件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);
}
}
大神,帮我看一下硬件IIC主从程序,不知道是不是哪个标志没有清,还是不行的,多谢了
在不?你的程序能给我发一份不?我现在调试从机的话,只能接收一个字节,如果想一次接收多个字节的话,在完成第一个字节的接收后 SR1的STOP会置位。不知道是什么问题