找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2531|回复: 2
收起左侧

stm32 iic,硬件iic主模式使用查询模式,从模式使用中断模式,已验证能正常收发数据

[复制链接]
ID:590667 发表于 2019-7-26 10:27 | 显示全部楼层 |阅读模式
  1. int main(void)
  2. {
  3.         u8 i = 0;
  4.         u16 temp = 0;
  5.   RCC_Configuration();         //时钟配置
  6.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);        //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
  7.         
  8.   IIC_Configuration1();
  9.         I2C_Configuration2();
  10.         
  11.         gpio_init();

  12. //        TIM2_Int_Init(719,999);  // 配置定时器TIM1每10ms产生中断,定时器计数频率为1kHz=72M/72000。
  13.         
  14.         //GPIO_SetBits(GPIOB,GPIO_Pin_0);
  15.          while(1)
  16.         {
  17.                 temp++;
  18.                 I2C_Master_BufferWrite(I2C1, I2C1_Buffer_Tx, 8, 0x20);
  19.    __nop();
  20.                 for(i=0;i<8;i++)
  21.                 {
  22.                         I2C1_Buffer_Tx[i] = 0;
  23.                         
  24.                 }
  25.     I2C_Master_BufferRead( I2C1, I2C1_Buffer_Tx,8, 0x20);
  26.                 for(i=0;i<8;i++)
  27.                 {
  28.                         I2C1_Buffer_Tx[i] = temp+i;
  29.                         
  30.                 }
  31.                
  32.         }
  33.         
  34. }

  35. #include  "i2c1.h"
  36. #include "delay.h"
  37. #include"stm32f10x.h"        

  38. u8 Tx_Idx1 = 0;
  39. u8 Rx_Idx1 = 0;
  40. u8 I2C1_Buffer_Tx[8] = {0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55};
  41. u8 I2C1_Buffer_Rx[8] = {0};

  42. u8 ReadingFlag = 0;
  43. /*IIC1从机模式*/
  44. void gpio_init()
  45. {
  46.          GPIO_InitTypeDef GPIO_InitStructure;
  47.          RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  48.          RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

  49.     //配置IO接口
  50.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_5;  //READY1/READY2
  51.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  52.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;        //
  53.     GPIO_Init(GPIOB, &GPIO_InitStructure);
  54.         
  55.                 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //Waring
  56.                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;        
  57.                 GPIO_Init(GPIOB, &GPIO_InitStructure);
  58. }

  59. //void I2C_Configuration1(void)
  60. //{
  61. //    GPIO_InitTypeDef GPIO_InitStructure;
  62. //        I2C_InitTypeDef  I2C_InitStructure;
  63. //        NVIC_InitTypeDef NVIC_InitStructure;

  64. //    //使能时钟
  65. //    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  66. //    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);
  67. //        
  68. //    //配置IO接口
  69. //    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; //PB6/PB7
  70. //    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  71. //    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;        //
  72. //    GPIO_Init(GPIOB, &GPIO_InitStructure);
  73. //         
  74. //                I2C_InitStructure.I2C_ClockSpeed=400000;        //I2C数据传输速度
  75. //                I2C_InitStructure.I2C_Mode=I2C_Mode_I2C;          //I2C模式设置         ,I2C模式,SMBus主模式,SMBus从模式
  76. //                I2C_InitStructure.I2C_DutyCycle=I2C_DutyCycle_2;
  77. //                I2C_InitStructure.I2C_OwnAddress1 =0x20;  //设备地址
  78. //                I2C_InitStructure.I2C_Ack =I2C_Ack_Enable;         
  79. //                I2C_InitStructure.I2C_AcknowledgedAddress=I2C_AcknowledgedAddress_7bit ;  //寻址模式,7bit或者10bit
  80. //                I2C_Init(I2C1,&I2C_InitStructure);        

  81. //                NVIC_InitStructure.NVIC_IRQChannel = I2C1_EV_IRQn;//事件中断
  82. //    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  83. //    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  84. //    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  85. //    NVIC_Init(&NVIC_InitStructure);

  86. //    NVIC_InitStructure.NVIC_IRQChannel = I2C1_ER_IRQn;//错误中断
  87. //    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  88. //    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;                 
  89. //    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  90. //    NVIC_Init(&NVIC_InitStructure);

  91. //    I2C_ITConfig(I2C1, I2C_IT_BUF | I2C_IT_EVT |I2C_IT_ERR, ENABLE);   

  92. //                I2C_Cmd(I2C1, ENABLE);
  93. //                 
  94. //}

  95. //void I2C1_EV_IRQHandler(void)            //I2C1事件中断响应函数 ,主要完成对上位机指令的响应
  96. //{
  97. //        switch(I2C_GetLastEvent(I2C1))
  98. //        {
  99. //                case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED:
  100. //                        {
  101. ////                                 I2C_GenerateSTOP(I2C2, DISABLE);                                 
  102. //                                 I2C_ClearFlag(I2C1,I2C_FLAG_ADDR);
  103. //                                 I2C_ClearFlag(I2C1,I2C_FLAG_BTF);
  104. //                                 break;
  105. //                        }
  106. //                case I2C_EVENT_SLAVE_BYTE_TRANSMITTED:
  107. //                                I2C_SendData(I2C1, I2C1_Buffer_Tx[Tx_Idx1++]);        
  108. //                                break;               
  109. //                case I2C_EVENT_SLAVE_BYTE_TRANSMITTING:                                //EV3
  110. //                                I2C_SendData(I2C1, I2C1_Buffer_Tx[Tx_Idx1++]);
  111. //                                        break;
  112. //                case I2C_EVENT_SLAVE_BYTE_RECEIVED:        
  113. //                           I2C_ClearFlag(I2C1,I2C_FLAG_BTF);
  114. //                                 I2C1_Buffer_Rx[Rx_Idx1++] =  I2C_ReceiveData(I2C1);                                          
  115. //                                break;
  116. //                case I2C_EVENT_SLAVE_STOP_DETECTED:
  117. //                           I2C_ClearFlag(I2C1,I2C_FLAG_STOPF);
  118. //                     I2C_GenerateSTOP(I2C1, DISABLE);
  119. //                           Rx_Idx1=0;  
  120. //                                //i2c_event = EVENT_OPCOD_NOTYET_READ;
  121. //                                break;
  122. //                default:

  123. //                                break;   

  124. //        }        
  125. //}
  126. //        

  127. //void I2C1_ER_IRQHandler(void)            //I2C2错误事件中断响应函数
  128. //{
  129. //   if (I2C_GetITStatus(I2C1, I2C_IT_AF))
  130. //         {
  131. //                         I2C_ClearITPendingBit(I2C1, I2C_IT_AF);
  132. //
  133. //                                Tx_Idx1 = 0;
  134. //                  //i2c_event = EVENT_OPCOD_NOTYET_READ;
  135. //                        
  136. //         }
  137. //         
  138. //         if (I2C_GetITStatus(I2C1, I2C_IT_BERR))
  139. //         {
  140. //                         I2C_ClearITPendingBit(I2C1, I2C_IT_BERR);
  141. //         }
  142. //}

  143. /*IIC1主机模式*/

  144. #define DEVICE_ADDRESS 0x20
  145. /*******************************************************************************
  146. * Function Name  : IIC_Configuration
  147. * Description    : 初始化IIC2外设
  148. * Input          : None
  149. * Output         : None
  150. * Return         : None
  151. *******************************************************************************/
  152. void IIC_Configuration1(void)
  153. {
  154.         //先定义结构体
  155.         GPIO_InitTypeDef         GPIO_InitStructure;
  156.   I2C_InitTypeDef    I2C_InitStructure;
  157.         
  158.         //要开了对应的gpio的时钟还有其他的外设的时钟,然后你配置寄存器才可以,软件仿真里面开时钟先后没有影响,但是实物里面,要先开时钟
  159.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);        //使能APB2外设的GPIOB的时钟,I2C2是PB_10 SCL,PB_11 SDA上面的复用         
  160.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 ,ENABLE);  //开启时钟
  161.         
  162.         //要对上面定义的两个结构体进行定义,首先PB要定义为复用的才行,而且是开漏复用
  163.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;         //选择PB_6是SCL引脚
  164.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;         //管脚频率为50MHZ
  165.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;         //输出模式为复用开漏输出
  166.         GPIO_Init(GPIOB,&GPIO_InitStructure);                                 //初始化GPIOB寄存器
  167.         
  168.         //配置I2C
  169.         I2C_DeInit(I2C1);//I2C1寄存器复位
  170.         I2C_InitStructure.I2C_ClockSpeed = 400000;          /*I2C的时钟频率100kHz ,不是I2C输入时钟的频率*/
  171.   I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;        
  172.   I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;  /*设置CCR寄存器的,占空比  快速模式下0:Tlow/Thigh = 2;1:Tlow/Thigh = 16/9 */
  173.   I2C_InitStructure.I2C_OwnAddress1 = 0x20 ;         /*这句话说的是stm32作为从机的时候它的地址,如果没有做从机不用理会这个值*/
  174.   I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;        /*应答使能 */
  175.   I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; /* */
  176.         I2C_Init(I2C1,&I2C_InitStructure);
  177.         
  178.         //使能I2C
  179.         I2C_Cmd(I2C1, ENABLE);
  180. }

  181. /*******************************************************************************
  182. 主机发送数据的流程:
  183. 1) 主机在检测到总线为“空闲状态”(即 SDA、SCL 线均为高电平)时,发送一个启动信号“S”,开始一次通信的开始
  184.   2) 主机接着发送一个命令字节。该字节由 7 位的外围器件地址和 1 位读写控制位 R/W组成(此时 R/W=0)
  185.   3) 相对应的从机收到命令字节后向主机回馈应答信号 ACK(ACK=0)
  186.   4) 主机收到从机的应答信号后开始发送第一个字节的数据
  187.   5) 从机收到数据后返回一个应答信号 ACK
  188.   6) 主机收到应答信号后再发送下一个数据字节
  189.   7) 当主机发送最后一个数据字节并收到从机的 ACK 后,通过向从机发送一个停止信号P结束本次通信并释放总线。从机收到P信号后也退出与主机之间的通信。
  190.   主机发送数据的程序
  191. *******************************************************************************//**/
  192. uint8_t I2C_Master_BufferWrite(I2C_TypeDef * I2Cx, uint8_t* pBuffer, uint32_t NumByteToWrite, uint8_t SlaveAddress)
  193. {
  194.     if(NumByteToWrite==0)
  195.         return 1;
  196.     /* 1.开始,发送一个s,也就是起始信号*/
  197.     I2C_GenerateSTART(I2Cx, ENABLE);
  198.                 ///判断EV5,看下函数定义可以发现,该事件是SB=1,MSL=1,BUSY=1 意思是起始条件已经发送了,然后是主模式,总线在通讯
  199.     while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));

  200.     /* 2.设备地址·/写 */
  201.     I2C_Send7bitAddress(I2Cx, SlaveAddress, I2C_Direction_Transmitter);
  202.     while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

  203.     /* 3.连续写数据 */
  204.     while(NumByteToWrite--)
  205.     {
  206.       I2C_SendData(I2Cx, *pBuffer);
  207.       while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
  208.       pBuffer++;
  209.     }

  210.     /* 4.停止 */
  211.     I2C_GenerateSTOP(I2Cx, ENABLE);//产生停止信号P,结束本次通讯释放总线
  212.     while ((I2Cx->CR1&0x200) == 0x200);//完成当前字节传输后释放 SCL 和 SDA 线
  213.                
  214.     return 0;
  215. }
  216. /*******************************************************************************
  217. IIC主机读取数据的具体流程:
  218.   1) 主机发送启动信号后,接着发送命令字节(其中 R/W=1)
  219.   2) 对应的从机收到地址字节后,返回一个应答信号并向主机发送数据
  220.   3) 主机收到数据后向从机反馈一个应答信号
  221.   4) 从机收到应答信号后再向主机发送下一个数据  
  222.   5) 当主机完成接收数据后,向从机发送一个“非应答信号(ACK=1)”,从机收到ACK=1 的非应答信号后便停止发送
  223.   6) 主机发送非应答信号后,再发送一个停止信号,释放总线结束通信.

  224. *******************************************************************************/
  225. uint8_t I2C_Master_BufferRead(I2C_TypeDef * I2Cx, uint8_t* pBuffer, uint32_t NumByteToRead, uint8_t SlaveAddress)
  226. {
  227.     if(NumByteToRead==0)
  228.         return 1;
  229.     ///等待总线空闲
  230.     while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));
  231.                 ///在接受一个字节(匹配地址或数据)之后返回应答
  232.     I2C_AcknowledgeConfig(I2Cx, ENABLE);
  233.                
  234.     /* 1.开始 */
  235.     I2C_GenerateSTART(I2Cx, ENABLE);
  236.     while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
  237.                
  238.     /* 2.设备地址·/写 */
  239.     I2C_Send7bitAddress(I2Cx, SlaveAddress, I2C_Direction_Transmitter);
  240.     while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

  241.     /* 3.开始*/
  242.     I2C_GenerateSTART(I2Cx, ENABLE);
  243.     while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
  244.                
  245.     /* 4.设备地址·/读 */
  246.     I2C_Send7bitAddress(I2Cx, SlaveAddress, I2C_Direction_Receiver);
  247.     while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));

  248.     /* 5.连续写数据 */
  249.     while (NumByteToRead)
  250.     {
  251.         if(NumByteToRead==1)
  252.         {
  253.             I2C_AcknowledgeConfig(I2Cx, DISABLE);
  254.             I2C_GenerateSTOP(I2Cx, ENABLE);//6.停止,非应答
  255.         }

  256.         while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED));  /* EV7 */
  257.         *pBuffer++ = I2C_ReceiveData(I2Cx);
  258.         NumByteToRead--;
  259.     }

  260.     I2C_AcknowledgeConfig(I2Cx, ENABLE);
  261.     return 0;
  262. }
复制代码

全部资料51hei下载地址:
stm32 IIC2.7z (190.48 KB, 下载次数: 44)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:592379 发表于 2019-7-31 10:32 | 显示全部楼层
下下来用了下不太行啊兄弟
回复

使用道具 举报

ID:144549 发表于 2019-10-11 15:55 | 显示全部楼层
试一下行不行
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表