Я пишу код для передачи и получения строки в формате массива. Я подключаю I2C1 к I2C2, оба на STM32F103 (синяя таблетка). I2C2 является ведущим, а I2C1 - ведомым, используя для получения прерывания. Однако, когда я проверяю, отправляя полученный массив в USART, он не работает. USART ничего не показывает. Смотри нравится, как-то застревает. Может кто-нибудь мне помочь? Это моя инициализация I2 C.
volatile uint8_t Tx_Index, Rx_Index;
uint8_t I2C_Buffer_Rx[64], I2C_Buffer_Tx[64] = "Hello World from I2C!\n";
void i2c_init(){
/* I2C initialize */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
I2C_InitTypeDef i2c_Init;
// i2c_Init.I2C_DutyCycle = I2C_DutyCycle_2;
i2c_Init.I2C_ClockSpeed = 100000; // Standard mode
i2c_Init.I2C_Mode = I2C_Mode_I2C; // configure CR1 (SMBTYPE, SMBUS or normal mode)
i2c_Init.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
i2c_Init.I2C_OwnAddress1 = 0x02;
i2c_Init.I2C_Ack = I2C_Ack_Disable;
I2C_Init(I2C2, &i2c_Init);
I2C_Cmd(I2C2, ENABLE);
/* Initialize GPIO as open drain alternate function */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitTypeDef gpio_Init;
gpio_Init.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11 |
GPIO_Pin_6 | GPIO_Pin_7; // SCL & SDA
gpio_Init.GPIO_Mode = GPIO_Mode_AF_OD;
gpio_Init.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOB, &gpio_Init);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
i2c_Init.I2C_ClockSpeed = 100000;
i2c_Init.I2C_Mode = I2C_Mode_I2C;
i2c_Init.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
i2c_Init.I2C_OwnAddress1 = 0x08;
i2c_Init.I2C_Ack = I2C_Ack_Enable;
I2C_Init(I2C1, &i2c_Init);
I2C_Cmd(I2C1, ENABLE);
I2C_ITConfig(I2C1, I2C_IT_BUF | I2C_IT_EVT, ENABLE);
Tx_Index = 0;
Rx_Index = 0;
}
Функция передачи для мастера:
void i2c_start(){
while(I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY));
// Generate start condition
I2C_GenerateSTART(I2C2, ENABLE);
while(!(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT)));
}
void i2c_stop(){
I2C_GenerateSTOP(I2C2, ENABLE);
while (I2C_GetFlagStatus(I2C2, I2C_FLAG_STOPF));
}
void i2c_SendAddress(uint8_t address, bool read){
address = address << 1;
if (read != false) {
I2C_AcknowledgeConfig(I2C2, ENABLE);
} else {
I2C_AcknowledgeConfig(I2C2, DISABLE);
}
I2C_Transmit(address);
while (!READ_BIT(I2C2->SR1, I2C_SR1_ADDR)); // Make sure address matched or
// address transmission finished
while (READ_BIT(I2C2->SR2, I2C_SR2_TRA) != read);// Make sure in right mode
// transmiter/receiver
}
void I2C_Transmit(uint8_t byte){
MODIFY_REG(I2C2->DR, I2C_DR_DR, byte);
}
void I2C_Write(uint8_t address, uint8_t *data){
i2c_start();
i2c_SendAddress(address, false);
for (uint8_t i = 0; i < 64; i++){
while (!(READ_BIT(I2C2->SR1, I2C_SR1_TXE) ||// Check if buffer is empty
READ_BIT(I2C2->SR1, I2C_SR1_BTF)));// Check if data transmission haven't done
I2C_Transmit(*data++); // I2C_Transmit(data);
}
while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
i2c_stop();
}
А вот прерывание подчиненного устройства:
void I2C1_EV_IRQHandler(void){
switch (I2C_GetLastEvent(I2C1)){
// Slave Receiver
case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED:
Rx_Index = 0;
break;
case I2C_EVENT_SLAVE_BYTE_RECEIVED:
// reading received data
I2C_Buffer_Rx[Rx_Index++] = (uint8_t) READ_REG(I2C1->DR);
break;
case I2C_EVENT_SLAVE_STOP_DETECTED:
(void)(I2C_GetITStatus(I2C1, I2C_IT_STOPF));
I2C_Cmd(I2C1, ENABLE);
Rx_Index = 0;
break;
default:
break;
}
}