STM32F105 硬件I2C从机发送,主机的时钟是400K,使用官方的代码,主机读时,第一个字节发送无效,一直都是0xFF,后面的字节是正确的,中断方式和DMA都是一样,不知道是F1速度不够还是怎样,有遇到过的吗?
初始化代码如下:
void hw_i2c_slave_init(void)
{
I2C_InitTypeDef I2C_InitStructure;
I2C_DeInit(I2C1);
/* I2C1 configuration ------------------------------------------------------*/
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;//模式
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = I2C_SLAVE_ADDRESS7;//这个就是作为从机的地址,一定要配置正确
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;//7位的地址
I2C_InitStructure.I2C_ClockSpeed = IIC_CLK_SPEED;
I2C_Init(I2C1, &I2C_InitStructure);
#ifdef SLAVE_DMA_USE
HW_I2c_DMA_Init();
I2C_Slave_BufferReadWrite(I2C1, DMA);
#else
/* Enable I2C1 event and buffer interrupts */
I2C_ITConfig(I2C1, I2C_IT_EVT | I2C_IT_BUF, ENABLE);
/* Enable I2C1 Error interrupts */
I2C_ITConfig(I2C1, I2C_IT_ERR, ENABLE);
#endif
I2C_Cmd(I2C1,ENABLE);
}
void HW_I2c_DMA_Init(void)
{
/* Enable the DMA1 clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
/* I2C1 TX DMA Channel configuration */
DMA_DeInit(I2C1_DMA_CHANNEL_TX);
I2CDMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)I2C1_DR_Address;
I2CDMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)0; /* This parameter will be configured durig communication */
I2CDMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; /* This parameter will be configured durig communication */
I2CDMA_InitStructure.DMA_BufferSize = 0xFFFF; /* This parameter will be configured durig communication */
I2CDMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
I2CDMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
I2CDMA_InitStructure.DMA_PeripheralDataSize = DMA_MemoryDataSize_Byte;
I2CDMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
I2CDMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
I2CDMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
I2CDMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(I2C1_DMA_CHANNEL_TX, &I2CDMA_InitStructure);
/* I2C1 RX DMA Channel configuration */
DMA_DeInit(I2C1_DMA_CHANNEL_RX);
DMA_Init(I2C1_DMA_CHANNEL_RX, &I2CDMA_InitStructure);
}
/**
* @brief Initializes DMA channel used by the I2C Write/read routines.
* @param None.
* @retval None.
*/
void I2C_DMAConfig(I2C_TypeDef* I2Cx, uint8_t* pBuffer, uint32_t BufferSize, uint32_t Direction)
{
/* Initialize the DMA with the new parameters */
if (Direction == I2C_DIRECTION_TX)
{
/* Configure the DMA Tx Channel with the buffer address and the buffer size */
I2CDMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)pBuffer;
I2CDMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
I2CDMA_InitStructure.DMA_BufferSize = (uint32_t)BufferSize;
if (I2Cx == I2C1)
{
I2CDMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)I2C1_DR_Address;
DMA_Cmd(I2C1_DMA_CHANNEL_TX, DISABLE);
DMA_Init(I2C1_DMA_CHANNEL_TX, &I2CDMA_InitStructure);
DMA_Cmd(I2C1_DMA_CHANNEL_TX, ENABLE);
}
else
{
I2CDMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)I2C2_DR_Address;
DMA_Cmd(I2C2_DMA_CHANNEL_TX, DISABLE);
DMA_Init(I2C2_DMA_CHANNEL_TX, &I2CDMA_InitStructure);
DMA_Cmd(I2C2_DMA_CHANNEL_TX, ENABLE);
}
}
else /* Reception */
{
/* Configure the DMA Rx Channel with the buffer address and the buffer size */
I2CDMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)pBuffer;
I2CDMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
I2CDMA_InitStructure.DMA_BufferSize = (uint32_t)BufferSize;
if (I2Cx == I2C1)
{
I2CDMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)I2C1_DR_Address;
DMA_Cmd(I2C1_DMA_CHANNEL_RX, DISABLE);
DMA_Init(I2C1_DMA_CHANNEL_RX, &I2CDMA_InitStructure);
DMA_Cmd(I2C1_DMA_CHANNEL_RX, ENABLE);
}
else
{
I2CDMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)I2C2_DR_Address;
DMA_Cmd(I2C2_DMA_CHANNEL_RX, DISABLE);
DMA_Init(I2C2_DMA_CHANNEL_RX, &I2CDMA_InitStructure);
DMA_Cmd(I2C2_DMA_CHANNEL_RX, ENABLE);
}
}
}
/**
* @brief Prepares the I2Cx slave for transmission.
* @param I2Cx: I2C1 or I2C2.
* @param Mode: DMA or Interrupt having the highest priority in the application.
* @retval : None.
*/
void I2C_Slave_BufferReadWrite(I2C_TypeDef* I2Cx,I2C_ProgrammingModel Mode)
{
/* Enable Event IT needed for ADDR and STOPF events ITs */
I2Cx->CR2 |= I2C_IT_EVT ;
/* Enable Error IT */
I2Cx->CR2 |= I2C_IT_ERR;
if (Mode == DMA) /* I2Cx Slave Transmission using DMA */
{
/* Enable I2Cx DMA requests */
I2Cx->CR2 |= CR2_DMAEN_Set;
}
else /* I2Cx Slave Transmission using Interrupt with highest priority in the application */
{
/* Enable Buffer IT (TXE and RXNE ITs) */
I2Cx->CR2 |= I2C_IT_BUF;
}
}
中断代码如下:
//事件中断处理函数
void I2C1_EV_IRQHandler(void)
{
#if 1
__IO uint32_t SR1Register =0;
__IO uint32_t SR2Register =0;
#ifdef SLAVE_DMA_USE
/* Read SR1 register */
SR1Register = I2C1->SR1;
/* If ADDR is set */
if ((SR1Register & 0x0002) == 0x0002)
{
/* In slave Transmitter/Receiver mode, when using DMA, the update of the buffer base address
and the buffer size should be done before clearing ADDR flag. In fact, the only
period when the slave has control on the bus(SCL is stretched so master can not initiate
transfers) is the period between ADDR is set and ADDR is cleared. otherwise, the master can
initiate transfers and the buffer size & the buffer address have not yet updated.*/
/* Update the DMA channels memory base address and count */
I2C_DMAConfig (I2C1, I2C_Buffer_Tx, I2C_BUFFER_LEN, I2C_DIRECTION_TX);
I2C_DMAConfig (I2C1, I2C_Buffer_Rx, I2C_BUFFER_LEN, I2C_DIRECTION_RX);
/* Clear ADDR by reading SR2 register */
SR2Register = I2C1->SR2;
}
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
一周热门 更多>