MCU:STM32L475RGT6(SYSCLK:80Mhz)
库
iic.c
#include "iic.h"
#include "main.h"
#include "gpio.h"
void IIC_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOB_CLK_ENABLE();//使能 GPIOB 时钟
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(SDA_GPIO_Port, SDA_Pin, GPIO_PIN_SET);
}
void SDA_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOB_CLK_ENABLE();//使能 GPIOB 时钟
GPIO_InitStruct.Pin = GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
void SDA_IN(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOB_CLK_ENABLE();//使能 GPIOB 时钟
GPIO_InitStruct.Pin = GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
void IIC_Start(void)
{
SDA_OUT(); //sda线输出
HAL_GPIO_WritePin(SDA_GPIO_Port, SDA_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_SET);
five_us_delay();
HAL_GPIO_WritePin(SDA_GPIO_Port, SDA_Pin, GPIO_PIN_RESET);//START:when CLK is high,DATA change form high to low
six_us_delay();
HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_RESET);//钳住I2C总线,准备发送或接收数据
}
void IIC_Stop(void)
{
SDA_OUT();//sda线输出
HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(SDA_GPIO_Port, SDA_Pin, GPIO_PIN_RESET);//STOP:when CLK is high DATA change form low to high
HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_SET);
six_us_delay();
HAL_GPIO_WritePin(SDA_GPIO_Port, SDA_Pin, GPIO_PIN_SET);//发送I2C总线结束信号
six_us_delay();
}
uint8_t IIC_Wait_Ack(void)
{
uint8_t tempTime=0;
SDA_IN(); //SDA设置为输入
HAL_GPIO_WritePin(SDA_GPIO_Port, SDA_Pin, GPIO_PIN_SET);
one_us_delay();
HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_SET);
one_us_delay();
while(HAL_GPIO_ReadPin(SDA_GPIO_Port, SDA_Pin))
{
tempTime++;
if(tempTime>250)
{
IIC_Stop();
return 1;
}
}
HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_RESET);//时钟输出0
return 0;
}
void IIC_Ack(void)
{
HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_RESET);
SDA_OUT();
HAL_GPIO_WritePin(SDA_GPIO_Port, SDA_Pin, GPIO_PIN_RESET);
two_us_delay();
HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_SET);
five_us_delay();
HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_RESET);
}
void IIC_NAck(void)
{
HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_RESET);
SDA_OUT();
HAL_GPIO_WritePin(SDA_GPIO_Port, SDA_Pin, GPIO_PIN_SET);
two_us_delay();
HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_SET);
five_us_delay();
HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_RESET);
}
void IIC_Send_Byte(uint8_t txd)
{
uint8_t t;
SDA_OUT();
HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_RESET);//拉低时钟开始数据传输
for(t=0;t<8;t++)
{
if((txd&0x80)>0) //0x80 1000 0000
HAL_GPIO_WritePin(SDA_GPIO_Port, SDA_Pin, GPIO_PIN_SET);
else
HAL_GPIO_WritePin(SDA_GPIO_Port, SDA_Pin, GPIO_PIN_RESET);
txd<<=1;
two_us_delay(); //对TEA5767这三个延时都是必须的
HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_SET);
two_us_delay();
HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_RESET);
two_us_delay();
}
}
uint8_t IIC_Read_Byte(uint8_t ack)
{
uint8_t i,receive=0;
SDA_IN();//SDA设置为输入
for(i=0;i<8;i++ )
{
HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_RESET);
two_us_delay();
HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_SET);
receive<<=1;
if(HAL_GPIO_ReadPin(SDA_GPIO_Port, SDA_Pin))receive++;
one_us_delay();
}
if (!ack)
IIC_NAck();//发送nACK
else
IIC_Ack(); //发送ACK
return receive;
}
void us_delay(uint32_t us)
{
// 每个循环迭代大约需要50纳秒
uint32_t iterations = (us * 1000) / 50;
for(uint32_t i = 0; i < iterations; i++) {
__asm("NOP");
}
}
void one_us_delay(void)
{
for(uint32_t i = 0; i < 6; i++) {
__asm("NOP");
}
}
void two_us_delay(void)
{
for(uint32_t i = 0; i < 13; i++) {
__asm("NOP");
}
}
void five_us_delay(void)
{
for(uint32_t i = 0; i < 37; i++) {
__asm("NOP");
}
}
void six_us_delay(void)
{
for(uint32_t i = 0; i < 45; i++) {
__asm("NOP");
}
}
iic.h
#ifndef _IIC_H
#define _IIC_H
#include "stdint.h"
//IO口配置
#define SCL_Pin GPIO_PIN_6
#define SCL_GPIO_Port GPIOB
#define SDA_Pin GPIO_PIN_7
#define SDA_GPIO_Port GPIOB
//IIC所有操作函数
void IIC_Init(void); //初始化IIC的IO口
void IIC_Start(void); //发送IIC开始信号
void IIC_Stop(void); //发送IIC停止信号
void IIC_Send_Byte(uint8_t txd); //IIC发送一个字节
uint8_t IIC_Read_Byte(uint8_t ack); //IIC读取一个字节
uint8_t IIC_Wait_Ack(void); //IIC等待ACK信号
void IIC_Ack(void); //IIC发送ACK信号
void IIC_NAck(void); //IIC不发送ACK信号
void us_delay(uint32_t us);
void one_us_delay(void);
void two_us_delay(void);
void five_us_delay(void);
void six_us_delay(void);
#endif
应用
#include "iic.h"
#define ADS1115_WRITE_ADDRESS 0x90
#define ADS1115_READ_ADDRESS 0x91
IIC_Init();
IIC_Start();
IIC_Send_Byte(ADS1115_WRITE_ADDRESS);
IIC_Wait_Ack();
IIC_Send_Byte(0b00000001);
IIC_Wait_Ack();
IIC_Send_Byte(0b10000100);
IIC_Wait_Ack();
IIC_Send_Byte(0b11100011);
IIC_Wait_Ack();
IIC_Stop();
HAL_Delay(10);
IIC_Start();
IIC_Send_Byte(ADS1115_WRITE_ADDRESS);
IIC_Wait_Ack();
IIC_Send_Byte(0b00000000);
IIC_Wait_Ack();
IIC_Stop();
HAL_Delay(10);
while(1)
{
IIC_Start();
IIC_Send_Byte(ADS1115_READ_ADDRESS);
IIC_Wait_Ack();
ads_data[0] = IIC_Read_Byte(1);
ads_data[1] = IIC_Read_Byte(0);
IIC_Stop();
HAL_Delay(10);
printf("Data: %x %x\n", ads_data[0], ads_data[1]);
}
基于普中科技标准库软件IIC代码进行改写