- #include <stdio.h>
- #include <stdint.h>
- #include "main.h"
- #include "type.h"
- #include "SwI2c.h"
- #include "n32g430.h"
- #include "timer.h"
- // PB8 scl PB9 sda
- #define SWI2C1_SCL_PORT GPIOB
- #define SWI2C1_SCL_PIN GPIO_PIN_8
- #define SWI2C1_SCL_CLOCK RCC_AHB_PERIPH_GPIOB
- #define SWI2C1_SCL_HIGH GPIO_Pins_Set(SWI2C1_SCL_PORT,SWI2C1_SCL_PIN)
- #define SWI2C1_SCL_LOW GPIO_Pins_Reset(SWI2C1_SCL_PORT,SWI2C1_SCL_PIN)
- #define SWI2C1_SDA_PORT GPIOB
- #define SWI2C1_SDA_PIN GPIO_PIN_9
- #define SWI2C1_SDA_CLOCK RCC_AHB_PERIPH_GPIOB
- #define SWI2C1_SDA_HIGH GPIO_Pins_Set(SWI2C1_SDA_PORT,SWI2C1_SDA_PIN)
- #define SWI2C1_SDA_LOW GPIO_Pins_Reset(SWI2C1_SDA_PORT,SWI2C1_SDA_PIN)
- #define SWI2C1_SDA_READ GPIO_Input_Pin_Data_Get(SWI2C1_SDA_PORT,SWI2C1_SDA_PIN)
- #define BIT0 0x01
- #define BIT7 0x80
- void SwI2c_Gpio_Init(void)
- {
- /* Define a structure of type GPIO_InitType */
- GPIO_InitType GPIO_InitStructure;
-
- /* Enable LED related GPIO peripheral clock */
- RCC_AHB_Peripheral_Clock_Enable(SWI2C1_SCL_CLOCK);
- RCC_AHB_Peripheral_Clock_Enable(SWI2C1_SDA_CLOCK);
-
- /* Assign default value to GPIO_InitStructure structure */
- GPIO_Structure_Initialize(&GPIO_InitStructure);
-
- /* Select the GPIO pin to control */
- GPIO_InitStructure.Pin = SWI2C1_SCL_PIN;
- /* Set pin mode to general push-pull output */
- GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUT_OD;
- GPIO_InitStructure.GPIO_Pull = GPIO_PULL_UP;
- /* Set the pin drive current to 4MA*/
- GPIO_InitStructure.GPIO_Current = GPIO_DS_4MA;
- GPIO_InitStructure.GPIO_Slew_Rate = GPIO_SLEW_RATE_FAST;
- /* Initialize GPIO */
- GPIO_Peripheral_Initialize(SWI2C1_SCL_PORT, &GPIO_InitStructure);
- /* Select the GPIO pin to control */
- GPIO_InitStructure.Pin = SWI2C1_SDA_PIN;
- /* Set pin mode to general push-pull output */
- GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUT_OD;
- GPIO_InitStructure.GPIO_Pull = GPIO_PULL_UP;
- /* Set the pin drive current to 4MA*/
- GPIO_InitStructure.GPIO_Current = GPIO_DS_4MA;
- GPIO_InitStructure.GPIO_Slew_Rate = GPIO_SLEW_RATE_FAST;
- /* Initialize GPIO */
- GPIO_Peripheral_Initialize(SWI2C1_SDA_PORT, &GPIO_InitStructure);
- SWI2C1_SDA_HIGH;
- SWI2C1_SCL_HIGH;
- }
- static void SwI2c_Delay_Us(int32_t us)
- {
- TIM3_Delay_Us(us);
- }
- static void SwI2c_Sda_Config_Output_mode(void)
- {
- GPIO_InitType GPIO_InitStructure;
- /* Assign default value to GPIO_InitStructure structure */
- GPIO_Structure_Initialize(&GPIO_InitStructure);
- /* Select the GPIO pin to control */
- GPIO_InitStructure.Pin = SWI2C1_SDA_PIN;
- /* Set pin mode to general push-pull output */
- GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUT_OD;
- GPIO_InitStructure.GPIO_Pull = GPIO_PULL_UP;
- /* Set the pin drive current to 4MA*/
- GPIO_InitStructure.GPIO_Current = GPIO_DS_4MA;
- GPIO_InitStructure.GPIO_Slew_Rate = GPIO_SLEW_RATE_FAST;
- /* Initialize GPIO */
- GPIO_Peripheral_Initialize(SWI2C1_SDA_PORT, &GPIO_InitStructure);
- SWI2C1_SDA_HIGH;
- }
- static void SwI2c_Sda_Config_Input_mode(void)
- {
- GPIO_InitType GPIO_InitStructure;
-
- /* Assign default value to GPIO_InitStructure structure */
- GPIO_Structure_Initialize(&GPIO_InitStructure);
- /* Select the GPIO pin to control */
- GPIO_InitStructure.Pin = SWI2C1_SDA_PIN;
- /* Set pin mode to general push-pull output */
- GPIO_InitStructure.GPIO_Mode = GPIO_MODE_INPUT;
- GPIO_InitStructure.GPIO_Pull = GPIO_PULL_UP;
- /* Set the pin drive current to 4MA*/
- GPIO_InitStructure.GPIO_Current = GPIO_DS_4MA;
- GPIO_InitStructure.GPIO_Slew_Rate = GPIO_SLEW_RATE_FAST;
- /* Initialize GPIO */
- GPIO_Peripheral_Initialize(SWI2C1_SDA_PORT, &GPIO_InitStructure);
- }
- void SwI2c_Start(void)
- {
- SWI2C1_SCL_LOW; // 先使SCL = 0, 为SDA上的电平改变做准备
- SwI2c_Delay_Us(2);
- SWI2C1_SDA_HIGH; // SDA = 1
- SwI2c_Sda_Config_Output_mode(); // sda OD 初始化输出1,
- SWI2C1_SDA_HIGH; // SDA = 1, 此时SDA的电平变化对通讯双方没有影响
- SwI2c_Delay_Us(2);
- SWI2C1_SCL_HIGH; // SCL = 1
- SwI2c_Delay_Us(2);
- SWI2C1_SDA_LOW; // SDA=0,产生下降沿,启动IIC通讯
- SwI2c_Delay_Us(2);
- SWI2C1_SCL_LOW; // SCL=0,为SDA上的电平改变做准备
- SwI2c_Delay_Us(2);
- }
- void SwI2c_Stop(void) //停止信号
- {
- SWI2C1_SCL_LOW ; // 先使SCL = 0, 为SDA上的电平改变做准备
- SwI2c_Delay_Us(2);
- SWI2C1_SDA_HIGH; // SDA = 1
- SwI2c_Sda_Config_Output_mode(); // sda OD 初始化输出1,
- SWI2C1_SDA_HIGH;
- SwI2c_Delay_Us(2);
- SWI2C1_SDA_LOW; // SDA=0,此时SDA的电平变化对通讯双方没有影响
- SwI2c_Delay_Us(2);
- SWI2C1_SCL_HIGH; // SCL=1
- SwI2c_Delay_Us(2);
- SWI2C1_SDA_HIGH; // SDA=1,结束IIC通讯
- SwI2c_Delay_Us(2); // SDA在结束后维持在高电平,如果有干扰脉冲产生而使得SDA
- // 变低,则干扰过后会恢复高电平. 此时SCL如果因干扰而处于
- return;
- }
- MI_U8 SwI2c_Wait_Ack(void) //等待应答信号:0-应答;1-非应答
- {
- MI_U8 uc_time = 0;
- SwI2c_Sda_Config_Input_mode(); //SDA定义为输入
- SWI2C1_SDA_HIGH;
- SwI2c_Delay_Us(1);
- SWI2C1_SCL_HIGH;
- SwI2c_Delay_Us(1);
- while (SWI2C1_SDA_READ)
- {
- uc_time++;
- if (uc_time > 250)
- {
- SwI2c_Stop();
- return 1;
- }
- }
- SWI2C1_SCL_LOW;
- return 0;
- }
- void SwI2c_Ack(void) //产生 ACK 应答
- {
- SWI2C1_SDA_HIGH; // SDA = 1
- SwI2c_Sda_Config_Output_mode(); // sda OD 初始化输出1,
- SWI2C1_SDA_HIGH; // SDA输出高电平
- SWI2C1_SDA_LOW; // 清SDA="0",CPU发低电平确认信号,
- SwI2c_Delay_Us(2);
- SWI2C1_SCL_HIGH; // 置SCL="1", 产生上升沿,发送一位确认数据
- SwI2c_Delay_Us(2);
- SWI2C1_SCL_LOW; // 清SCL="0",为SDA上的电平改变做准备
- return;
- }
- void Swi2c_No_Ack(void) //产生 NACK 非应答
- {
- SWI2C1_SDA_HIGH; // SDA = 1
- SwI2c_Sda_Config_Output_mode(); // sda OD 初始化输出1,
- SWI2C1_SDA_HIGH; // 置SDA=1, CPU发"高电平非应答确认"信号
- SwI2c_Delay_Us(2);
- SWI2C1_SCL_HIGH; // 置SCL="1", 产生上升沿,发送一位确认数据
- SwI2c_Delay_Us(2);
- SWI2C1_SCL_LOW; // 清SCL="0",为SDA上的电平改变做准备
- return;
- }
- //IIC 发送一个字节
- MI_BOOL SwI2c_Write_Byte(MI_U8 data)
- {
- MI_U8 m; // SDA = 1
- SwI2c_Sda_Config_Output_mode(); // sda OD 初始化输出1,
- for (m = 0; m < 8; m++)
- {
- SWI2C1_SCL_LOW; // SCL=0,为SDA上的电平改变做准备
- SwI2c_Delay_Us(2);
- if (data & BIT7) // 由最高位开始发送
- {
- SWI2C1_SDA_HIGH;
- }
- else
- {
- SWI2C1_SDA_LOW;
- }
- SwI2c_Delay_Us(2);
- SWI2C1_SCL_HIGH; // SCL="1",产生上升沿,发送一位数据
- SwI2c_Delay_Us(2);
- data <<= 1;
- }
- SWI2C1_SCL_LOW; // 清SCL="0",产生下降沿, 器件使SDA="0"
- SwI2c_Delay_Us(2);
- SwI2c_Sda_Config_Input_mode(); // SDA改为输入,准备接收确认应答
- SWI2C1_SCL_HIGH; // SCL="1",让CPU在此期间读取SDA上的信号
- for (m = 0; m < 8; m++)
- {
- SwI2c_Delay_Us(2);
- if (SWI2C1_SDA_READ == 0)
- {
- SWI2C1_SCL_LOW; // 清SCL="0",为SDA上的电平改变做准备
- SwI2c_Delay_Us(2);
- return MI_TRUE; // 收到正确的低电平应答
- }
- }
- SWI2C1_SCL_LOW; // 清SCL="0",为SDA上的电平改变做准备
- return MI_FALSE;
- }
- //读一个字节
- MI_U8 SwI2c_Read_Byte()
- {
- MI_U8 m, data;
- SwI2c_Sda_Config_Input_mode(); // SDA改为输入,准备接收数据
- data = 0;
- for (m = 0; m < 8; m++)
- {
- SWI2C1_SCL_LOW; // SCL="0",产生下降沿, 器件串出一位数据
- SwI2c_Delay_Us(2);
- SWI2C1_SCL_HIGH; // 置SCL="1", 让CPU在此期间读取SDA上的信号
- SwI2c_Delay_Us(2);
- data <<= 1;
- if (SWI2C1_SDA_READ)
- {
- data |= BIT0;
- }
- else
- {
- data &= (~BIT0);
- }
- }
- SWI2C1_SCL_LOW; // 清SCL="0",为SDA上的电平改变做准备
- return data;
- }
- MI_BOOL SwI2c_Device_Write_Data(MI_U8 device_addr,MI_U8 *reg_addr,
- uint16_t reg_len,const MI_U8 *buf,MI_U8 len)
- {
- SwI2c_Start();
- SwI2c_Write_Byte(device_addr);
- while (reg_len != 0)
- {
- if (SwI2c_Write_Byte(*reg_addr++) == MI_FALSE) // 发送一字节数据
- {
- SwI2c_Stop();
- return MI_FALSE;
- }
- reg_len--;
- }
- while (len != 0)
- {
- if (SwI2c_Write_Byte( *buf++) == MI_FALSE) // 发送一字节数据
- {
- SwI2c_Stop();
- return MI_FALSE;
- }
- len--;
- }
- SwI2c_Stop();
- return MI_TRUE;
- }
- MI_U8 SwI2c_Device_Read_Data(MI_U8 device_addr,MI_U8 *reg_addr,
- uint16_t reg_len, MI_U8 *buf,MI_U8 len)
- {
- SwI2c_Start();
- SwI2c_Write_Byte(device_addr);
- while (reg_len != 0)
- {
- if (SwI2c_Write_Byte(*reg_addr++) == MI_FALSE) // 发送一字节数据
- {
- SwI2c_Stop();
- return MI_FALSE;
- }
- reg_len--;
- }
- SwI2c_Start();
- SwI2c_Write_Byte(device_addr + 1);
- while (1)
- {
- *buf++ = SwI2c_Read_Byte(); // 接收一字节
- len--;
- if (0 == len)
- {
- break;
- }
- SwI2c_Ack(); // 未读完,CPU发低电平确认应答信号,以便读取下8位数据
- }
- Swi2c_No_Ack(); // 已读完所有的数据,CPU发"高电平非应答确认"信号
- SwI2c_Stop();
- return MI_TRUE;
- }
.h文件
- #ifndef _SWI2C_H__
- #define _SWI2C_H__
- void SwI2c_Gpio_Init(void);
- MI_U8 SwI2c_Device_Read_Data(MI_U8 device_addr,MI_U8 *reg_addr,
- uint16_t reg_len,MI_U8 *buf,MI_U8 len);
- MI_BOOL SwI2c_Device_Write_Data(MI_U8 device_addr,MI_U8 *reg_addr,
- uint16_t reg_len,const MI_U8 *buf,MI_U8 len);
- #endif //_SWI2C_H__
3、延时函数换成自己的即可,楼主为了准确性,延时函数开了一个定时器。
prescaler = 64-1 ,1us加一次,Period设置最大,最大延时数就是这个。
相应代码如下
- void TIM3_Init(void)
- {
- RCC_APB1_Peripheral_Clock_Enable(RCC_APB1_PERIPH_TIM3);
- TIM_TimeBaseInitType TIM_TimeBaseStructure;
- TIM_Base_Struct_Initialize(&TIM_TimeBaseStructure);
- TIM_TimeBaseStructure.Period = 65535-1;
- TIM_TimeBaseStructure.Prescaler = 64-1;
- TIM_TimeBaseStructure.ClkDiv = 0;
- TIM_TimeBaseStructure.CntMode = TIM_CNT_MODE_UP;
- TIM_Base_Initialize(TIM3, &TIM_TimeBaseStructure);
- TIM_Base_Reload_Mode_Set(TIM2, TIM_PSC_RELOAD_MODE_IMMEDIATE);
- }
- void TIM3_Delay_Us(__IO uint32_t us)
- {
- TIM_Base_Count_Set(TIM3,0);
- TIM_On(TIM3);
- while(TIM_Base_Count_Get(TIM3) < us);
- TIM_Off(TIM3);
- }