标题:
stm32 iic,硬件iic主模式使用查询模式,从模式使用中断模式,已验证能正常收发数据
[打印本页]
作者:
zxp123456
时间:
2019-7-26 10:27
标题:
stm32 iic,硬件iic主模式使用查询模式,从模式使用中断模式,已验证能正常收发数据
int main(void)
{
u8 i = 0;
u16 temp = 0;
RCC_Configuration(); //时钟配置
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
IIC_Configuration1();
I2C_Configuration2();
gpio_init();
// TIM2_Int_Init(719,999); // 配置定时器TIM1每10ms产生中断,定时器计数频率为1kHz=72M/72000。
//GPIO_SetBits(GPIOB,GPIO_Pin_0);
while(1)
{
temp++;
I2C_Master_BufferWrite(I2C1, I2C1_Buffer_Tx, 8, 0x20);
__nop();
for(i=0;i<8;i++)
{
I2C1_Buffer_Tx[i] = 0;
}
I2C_Master_BufferRead( I2C1, I2C1_Buffer_Tx,8, 0x20);
for(i=0;i<8;i++)
{
I2C1_Buffer_Tx[i] = temp+i;
}
}
}
#include "i2c1.h"
#include "delay.h"
#include"stm32f10x.h"
u8 Tx_Idx1 = 0;
u8 Rx_Idx1 = 0;
u8 I2C1_Buffer_Tx[8] = {0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55};
u8 I2C1_Buffer_Rx[8] = {0};
u8 ReadingFlag = 0;
/*IIC1从机模式*/
void gpio_init()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
//配置IO接口
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_5; //READY1/READY2
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //Waring
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
//void I2C_Configuration1(void)
//{
// GPIO_InitTypeDef GPIO_InitStructure;
// I2C_InitTypeDef I2C_InitStructure;
// NVIC_InitTypeDef NVIC_InitStructure;
// //使能时钟
// RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
// RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);
//
// //配置IO接口
// GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; //PB6/PB7
// GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; //
// GPIO_Init(GPIOB, &GPIO_InitStructure);
//
// I2C_InitStructure.I2C_ClockSpeed=400000; //I2C数据传输速度
// I2C_InitStructure.I2C_Mode=I2C_Mode_I2C; //I2C模式设置 ,I2C模式,SMBus主模式,SMBus从模式
// I2C_InitStructure.I2C_DutyCycle=I2C_DutyCycle_2;
// I2C_InitStructure.I2C_OwnAddress1 =0x20; //设备地址
// I2C_InitStructure.I2C_Ack =I2C_Ack_Enable;
// I2C_InitStructure.I2C_AcknowledgedAddress=I2C_AcknowledgedAddress_7bit ; //寻址模式,7bit或者10bit
// I2C_Init(I2C1,&I2C_InitStructure);
// NVIC_InitStructure.NVIC_IRQChannel = I2C1_EV_IRQn;//事件中断
// NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
// NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
// NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
// NVIC_Init(&NVIC_InitStructure);
// NVIC_InitStructure.NVIC_IRQChannel = I2C1_ER_IRQn;//错误中断
// NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
// NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
// NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
// NVIC_Init(&NVIC_InitStructure);
// I2C_ITConfig(I2C1, I2C_IT_BUF | I2C_IT_EVT |I2C_IT_ERR, ENABLE);
// I2C_Cmd(I2C1, ENABLE);
//
//}
//void I2C1_EV_IRQHandler(void) //I2C1事件中断响应函数 ,主要完成对上位机指令的响应
//{
// switch(I2C_GetLastEvent(I2C1))
// {
// case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED:
// {
//// I2C_GenerateSTOP(I2C2, DISABLE);
// I2C_ClearFlag(I2C1,I2C_FLAG_ADDR);
// I2C_ClearFlag(I2C1,I2C_FLAG_BTF);
// break;
// }
// case I2C_EVENT_SLAVE_BYTE_TRANSMITTED:
// I2C_SendData(I2C1, I2C1_Buffer_Tx[Tx_Idx1++]);
// break;
// case I2C_EVENT_SLAVE_BYTE_TRANSMITTING: //EV3
// I2C_SendData(I2C1, I2C1_Buffer_Tx[Tx_Idx1++]);
// break;
// case I2C_EVENT_SLAVE_BYTE_RECEIVED:
// I2C_ClearFlag(I2C1,I2C_FLAG_BTF);
// I2C1_Buffer_Rx[Rx_Idx1++] = I2C_ReceiveData(I2C1);
// break;
// case I2C_EVENT_SLAVE_STOP_DETECTED:
// I2C_ClearFlag(I2C1,I2C_FLAG_STOPF);
// I2C_GenerateSTOP(I2C1, DISABLE);
// Rx_Idx1=0;
// //i2c_event = EVENT_OPCOD_NOTYET_READ;
// break;
// default:
// break;
// }
//}
//
//void I2C1_ER_IRQHandler(void) //I2C2错误事件中断响应函数
//{
// if (I2C_GetITStatus(I2C1, I2C_IT_AF))
// {
// I2C_ClearITPendingBit(I2C1, I2C_IT_AF);
//
// Tx_Idx1 = 0;
// //i2c_event = EVENT_OPCOD_NOTYET_READ;
//
// }
//
// if (I2C_GetITStatus(I2C1, I2C_IT_BERR))
// {
// I2C_ClearITPendingBit(I2C1, I2C_IT_BERR);
// }
//}
/*IIC1主机模式*/
#define DEVICE_ADDRESS 0x20
/*******************************************************************************
* Function Name : IIC_Configuration
* Description : 初始化IIC2外设
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void IIC_Configuration1(void)
{
//先定义结构体
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
//要开了对应的gpio的时钟还有其他的外设的时钟,然后你配置寄存器才可以,软件仿真里面开时钟先后没有影响,但是实物里面,要先开时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //使能APB2外设的GPIOB的时钟,I2C2是PB_10 SCL,PB_11 SDA上面的复用
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 ,ENABLE); //开启时钟
//要对上面定义的两个结构体进行定义,首先PB要定义为复用的才行,而且是开漏复用
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; //选择PB_6是SCL引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //管脚频率为50MHZ
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; //输出模式为复用开漏输出
GPIO_Init(GPIOB,&GPIO_InitStructure); //初始化GPIOB寄存器
//配置I2C
I2C_DeInit(I2C1);//I2C1寄存器复位
I2C_InitStructure.I2C_ClockSpeed = 400000; /*I2C的时钟频率100kHz ,不是I2C输入时钟的频率*/
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; /*设置CCR寄存器的,占空比 快速模式下0:Tlow/Thigh = 2;1:Tlow/Thigh = 16/9 */
I2C_InitStructure.I2C_OwnAddress1 = 0x20 ; /*这句话说的是stm32作为从机的时候它的地址,如果没有做从机不用理会这个值*/
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; /*应答使能 */
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; /* */
I2C_Init(I2C1,&I2C_InitStructure);
//使能I2C
I2C_Cmd(I2C1, ENABLE);
}
/*******************************************************************************
主机发送数据的流程:
1) 主机在检测到总线为“空闲状态”(即 SDA、SCL 线均为高电平)时,发送一个启动信号“S”,开始一次通信的开始
2) 主机接着发送一个命令字节。该字节由 7 位的外围器件地址和 1 位读写控制位 R/W组成(此时 R/W=0)
3) 相对应的从机收到命令字节后向主机回馈应答信号 ACK(ACK=0)
4) 主机收到从机的应答信号后开始发送第一个字节的数据
5) 从机收到数据后返回一个应答信号 ACK
6) 主机收到应答信号后再发送下一个数据字节
7) 当主机发送最后一个数据字节并收到从机的 ACK 后,通过向从机发送一个停止信号P结束本次通信并释放总线。从机收到P信号后也退出与主机之间的通信。
主机发送数据的程序
*******************************************************************************//**/
uint8_t I2C_Master_BufferWrite(I2C_TypeDef * I2Cx, uint8_t* pBuffer, uint32_t NumByteToWrite, uint8_t SlaveAddress)
{
if(NumByteToWrite==0)
return 1;
/* 1.开始,发送一个s,也就是起始信号*/
I2C_GenerateSTART(I2Cx, ENABLE);
///判断EV5,看下函数定义可以发现,该事件是SB=1,MSL=1,BUSY=1 意思是起始条件已经发送了,然后是主模式,总线在通讯
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
/* 2.设备地址·/写 */
I2C_Send7bitAddress(I2Cx, SlaveAddress, I2C_Direction_Transmitter);
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
/* 3.连续写数据 */
while(NumByteToWrite--)
{
I2C_SendData(I2Cx, *pBuffer);
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
pBuffer++;
}
/* 4.停止 */
I2C_GenerateSTOP(I2Cx, ENABLE);//产生停止信号P,结束本次通讯释放总线
while ((I2Cx->CR1&0x200) == 0x200);//完成当前字节传输后释放 SCL 和 SDA 线
return 0;
}
/*******************************************************************************
IIC主机读取数据的具体流程:
1) 主机发送启动信号后,接着发送命令字节(其中 R/W=1)
2) 对应的从机收到地址字节后,返回一个应答信号并向主机发送数据
3) 主机收到数据后向从机反馈一个应答信号
4) 从机收到应答信号后再向主机发送下一个数据
5) 当主机完成接收数据后,向从机发送一个“非应答信号(ACK=1)”,从机收到ACK=1 的非应答信号后便停止发送
6) 主机发送非应答信号后,再发送一个停止信号,释放总线结束通信.
*******************************************************************************/
uint8_t I2C_Master_BufferRead(I2C_TypeDef * I2Cx, uint8_t* pBuffer, uint32_t NumByteToRead, uint8_t SlaveAddress)
{
if(NumByteToRead==0)
return 1;
///等待总线空闲
while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));
///在接受一个字节(匹配地址或数据)之后返回应答
I2C_AcknowledgeConfig(I2Cx, ENABLE);
/* 1.开始 */
I2C_GenerateSTART(I2Cx, ENABLE);
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
/* 2.设备地址·/写 */
I2C_Send7bitAddress(I2Cx, SlaveAddress, I2C_Direction_Transmitter);
while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
/* 3.开始*/
I2C_GenerateSTART(I2Cx, ENABLE);
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
/* 4.设备地址·/读 */
I2C_Send7bitAddress(I2Cx, SlaveAddress, I2C_Direction_Receiver);
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
/* 5.连续写数据 */
while (NumByteToRead)
{
if(NumByteToRead==1)
{
I2C_AcknowledgeConfig(I2Cx, DISABLE);
I2C_GenerateSTOP(I2Cx, ENABLE);//6.停止,非应答
}
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED)); /* EV7 */
*pBuffer++ = I2C_ReceiveData(I2Cx);
NumByteToRead--;
}
I2C_AcknowledgeConfig(I2Cx, ENABLE);
return 0;
}
复制代码
全部资料51hei下载地址:
stm32 IIC2.7z
(190.48 KB, 下载次数: 44)
2019-7-26 22:46 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
月之光芒
时间:
2019-7-31 10:32
下下来用了下不太行啊兄弟
作者:
jayzay008
时间:
2019-10-11 15:55
试一下行不行
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1