首先I2C和SMBus是兼容的,亲测把初始化换成SMBus或者I2C都是可以通信的。
这几天老师因为工控机上SMBus接口长得好看一点。。。。。。。所以非要我搞SMBus的通信。。。。。。。其实旁边就是UART接口,就是接线麻烦一点。
反正他既然说了就搞呗,结果发现网上关于I2C用从机中断的资料巨少,就想着把代码po上来共享一下。
#include "IIC.h"
#include "delay.h"
#include "stm32f4xx_i2c.h"
#include "Exti.h"
//********接口定义*********************************************************//
//调用库函数将
//程序代码如下:
//************************************************************************//
void IIC_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //GPIO 结构体定义
I2C_InitTypeDef I2C_InitStructure; //I2C 结构体定义
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE); //I2C 时钟使能
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);
//RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
/* Configure and enable SI2CMASTER interrupt --------------------------------*/
//RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, ENABLE);
//RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, DISABLE);
//*I2C1-模式 配置*//
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; //选择I2C功能
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; //I2C应答使能
I2C_InitStructure.I2C_ClockSpeed = 400000; //时钟速率,以 HZ 为单位的,最高为 400khz
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; //该参数只有在 I2C 工作在快速模式(时钟工作频率高于 100KHz)下才有意义
I2C_InitStructure.I2C_OwnAddress1 =0x30; //设置第一个设备自身地址
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; //
I2C_Init(I2C1, &I2C_InitStructure); //初始化结构体配置
// IIC_SCL=1;
// IIC_SDA=1;
/* 1 bit for pre-emption priority, 3 bits for subpriority */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
/* Configure and enable I2CMASTER interrupt --------------------------------*/
NVIC_InitStructure.NVIC_IRQChannel = I2C1_EV_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =0x01;
NVIC_InitStructure.NVIC_IRQChannelSubPriority =0x01;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
//*I2C1-IO 口配置*//
//使能GPIOB时钟
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能的开漏输出
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; //使能B.6和B.7
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度最高50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化结构体配置
//I2C_ITConfig(I2C1,I2C_IT_EVT|I2C_IT_BUF|I2C_IT_ERR,ENABLE);
I2C_ITConfig(I2C1,I2C_IT_EVT|I2C_IT_BUF,ENABLE);
I2C_Cmd(I2C1, ENABLE); //使能 I2C1
}
//extern u32 BufferSize ;
//extern u8 I2C1_ADDRESS ;
//extern u8 I2C2_ADDRESS ;
extern vu8 I2C1_Buffer_Tx[];
extern vu8 I2C1_Buffer_Rx[];
vu32 Tx_Counter = 0;
vu32 Rx_Counter = 0;
vu32 USART_Counter=0;
#define size 100
//vu32 show_counter1 = 0;
//vu32 show_counter2 = 0;
vu8 I2C1_Buffer_Rx[size]= {0};
int I2C_Tx = KEY_LEN;
void I2C1_EV_IRQHandler(void)
{
__IO uint16_t SR1Register =0;
__IO uint16_t SR2Register =0;
SR1Register = I2C1->SR1;
SR2Register = I2C1->SR2;
// 从机发送
// 从模式(MSL = 0)
if((SR2Register & 0x0005) == 0x0004)
{
// ADDR
if((SR1Register & 0x0002) == 0x0002)
{
// 清除标志
SR1Register = 0;
SR2Register = 0;
//Tx_Counter= 0;
}
//TxE:DR为空
if((SR1Register & 0x0080) == 0x0080)
{
SR1Register = 0;
SR2Register = 0;
I2C1->DR = I2C_Tx;
//I2C_GenerateSTOP(I2C1, ENABLE);
}
//STOPF
if((SR1Register & 0x0010) == 0x0010)
{
I2C1->CR1 |= 0x0001;
SR1Register = 0;
SR2Register = 0;
// Tx_Counter= 5;
}
//TIME_OUT
if((SR1Register & 0x4000) == 0x4000)
{
I2C1->CR1 |= 0x0001;
SR1Register = 0;
SR2Register = 0;
}
}
// 从机接收
// 从模式(MSL = 0)
else if((SR2Register &0x0005) == 0x0000)
{
// (ADDR = 1: EV1)
if((SR1Register & 0x0002) == 0x0002)
{
SR1Register = 0;
SR2Register = 0;
Rx_Counter = 0;
USART_Counter=0;
}
// (RXNE = 1: EV2)
if((SR1Register & 0x0040) == 0x0040)
{
I2C_Tx = KEY_LEN;
delay_ms(1);
Rx_Counter++;
if(Rx_Counter>=2)
{
I2C1_Buffer_Rx[Rx_Counter]=I2C1->DR;
if(Rx_Counter>=3)
{
I2C1_Buffer_Rx[USART_Counter]=I2C1_Buffer_Rx[Rx_Counter];
delay_ms(1);
USART_SendData( UART4, I2C1_Buffer_Rx[USART_Counter++] );
}
}
SR1Register = 0;
SR2Register = 0;
}
// (STOPF =1: EV4)
if(( SR1Register & 0x0010) == 0x0010)
{
I2C1->CR1 |= 0x0001;
SR1Register = 0;
SR2Register = 0;
// Flag_RcvOK = 1;
}
}
}
I2C_Tx就是我发送的数据,只发送这么一个字节的数据,发送多个数据的同学可以试着改一下程序。然后我是在电脑在给我发一个发送的时候把I2C_Tx赋值为初始值,这样我们就知道电脑已经读了这个数据了。
完整的项目代码已经上传到我的CSDN上,这个工程是一个按键板的工程,有使用pwm做蜂鸣器,按键中断检测按键,和按键扫描。
喜欢的话记得点赞哦~~~