使用GPIO口实现i2c总线控制
i2c.h
#ifndef __I2C_H__
#define __I2C_H__
#define I2C_SDA_OUT do{GPIOF->MODER &= (~(0x3<<0x1E)); GPIOF->MODER |= (0x1<<0x1E);}while(0)
#define I2C_SDA_IN do{GPIOF->MODER &= (~(0x3<<0x1E)); }while(0)
#define I2C_SCL_HIGH do{GPIOF->ODR |= (0x1<<14);}while(0)
#define I2C_SCL_LOW do{GPIOF->ODR &= (~(0x1<<14));}while(0)
#define I2C_SDA_HIGH do{GPIOF->ODR |= (0x1<<15);}while(0)
#define I2C_SDA_LOW do{GPIOF->ODR &= (~(0x1<<15));}while(0)
//#define I2C_SDA_READ do{(GPIOF->IDR & (0x1<<0xF))>>0xF}while(0)
extern void printf(const char *fmt, ...);
//delay in microsecond
void delay_us(void);
//delay in millisecond
void delay(int ms);
//start signal
void i2c_start(void);
//stop signal
void i2c_stop(void);
//write one byte
void i2c_write_byte(unsigned char dat);
//read one byte
unsigned char i2c_read_byte();
//wait for acknowledge
unsigned char i2c_get_ack(void);
//send acknowledge
void i2c_send_ack(void);
//send not acknowledge
void i2c_send_nack(void);
void i2c_gpio_init();
void i2c_si7006_init();
unsigned short i2c_read_hum();
short i2c_read_tmp();
#endif
i2c.c
#include "i2c.h"
#include "stm32mp1xx_rcc.h"
#include "stm32mp1xx_gpio.h"
/*
port: GPIOF
pin: I2C1_SCL/PF14
pin: I2C1_SDA/PF15
RCC: PF14/PF15 AHB4
si7006 address 0x40
*/
//delay in microsecond
void delay_us(void){
unsigned int i = 2000;
while(i--);
}
//delay in millisecond
//start signal
void i2c_start(void){
I2C_SDA_OUT;
I2C_SCL_HIGH;
I2C_SDA_HIGH;
delay_us();
I2C_SDA_LOW;
delay_us();
I2C_SCL_LOW;
}
//stop signal
void i2c_stop(void){
I2C_SDA_OUT;
I2C_SCL_LOW;
I2C_SDA_LOW;
delay_us();
I2C_SCL_HIGH;
delay_us();
I2C_SDA_HIGH;
}
//write one byte
void i2c_write_byte(unsigned char dat){
I2C_SDA_OUT;
for(int i=0;i<8;i++){
I2C_SCL_LOW;
delay_us();
if((dat&(0x1<<0x7))==1){
I2C_SDA_HIGH;
}else{
I2C_SDA_LOW;
}
delay_us();
I2C_SCL_HIGH;
delay_us();
delay_us();
dat=(dat<<0x1);
}
}
//read one byte
unsigned char i2c_read_byte(){
I2C_SDA_IN;
unsigned char dat=0;
for(int i=0;i<8;i++){
I2C_SCL_LOW;
delay_us();
delay_us();
I2C_SCL_HIGH;
dat=(dat<<0x1) | GPIOF->IDR;
delay_us();
delay_us();
}
return dat;
}
//get acknowledge
unsigned char i2c_get_ack(void){
I2C_SDA_IN;
I2C_SCL_LOW;
I2C_SDA_HIGH;
delay_us();
delay_us();
I2C_SCL_LOW;
delay_us();
return (GPIOF->IDR & (0x1<<0xF))>>0xF;
}
//send acknowledge
void i2c_send_ack(void){
I2C_SDA_OUT;
I2C_SCL_LOW;
delay_us();
I2C_SDA_LOW;
delay_us();
I2C_SCL_HIGH;
delay_us();
delay_us();
I2C_SCL_LOW;
}
//send not acknowledge
void i2c_send_nack(void){
I2C_SDA_OUT;
I2C_SCL_LOW;
delay_us();
I2C_SDA_HIGH;
delay_us();
I2C_SCL_HIGH;
delay_us();
delay_us();
I2C_SCL_LOW;
}
void i2c_gpio_init(){
//enable GPIOF
RCC->MP_AHB4ENSETR |= (0x1<<0x5);
//set GPIOF14 to ouput mode
GPIOF->MODER &= (~(0x3<<0x1c));
GPIOF->MODER |= (0x1<<0x1c);
}
void i2c_si7006_init(){
i2c_start();
i2c_write_byte(0x80);
if(i2c_get_ack()==0){printf("i2c_si7006_init--------------1");}
i2c_write_byte(0XE6);
if(i2c_get_ack()==0){printf("i2c_si7006_init--------------2");}
i2c_write_byte(0X3A);
if(i2c_get_ack()==0){printf("i2c_si7006_init--------------3");}
i2c_stop();
};
unsigned short i2c_read_hum(){
unsigned short hum=0;
unsigned char hum_high,hum_low;
i2c_start();
i2c_write_byte(0x80);
if(i2c_get_ack()==0){printf("i2c_read_hum--------------1");}
i2c_write_byte(0XE5);
if(i2c_get_ack()==0){printf("i2c_read_hum--------------2");}
i2c_start();
i2c_write_byte(0x81);
hum_high=i2c_read_byte();
i2c_send_ack();
hum_low=i2c_read_byte();
i2c_send_nack();
i2c_stop();
hum=(hum_high<<0x8) | hum_low;
return hum;
}
short i2c_read_tmp(){
short tmp=0;
char tmp_high,tmp_low;
i2c_start();
i2c_write_byte(0x80);
if(i2c_get_ack()==0){printf("i2c_read_tmp--------------1");}
i2c_write_byte(0XE5);
if(i2c_get_ack()==0){printf("i2c_read_tmp--------------2");}
i2c_start();
i2c_write_byte(0x81);
tmp_high=i2c_read_byte();
i2c_send_ack();
tmp_low=i2c_read_byte();
i2c_send_nack();
i2c_stop();
tmp=(tmp_high<<0x8) | tmp_low;
return tmp;
}
main.c
#include"led.h"
//#include "fan.h"
#include "uart4.h"
#include "key.h"
#include "i2c.h"
extern void printf(const char *fmt, ...);
//封装延时函数
void delay(int ms)
{
int i,j;
for(i=0;i<ms;i++)
{
for(j=0;j<2000;j++)
{}
}
}
int main()
{
all_led_init();
/*
fan_init();
*/
uart4_init();
key_init();
i2c_gpio_init();
i2c_si7006_init();
while(1)
{
/*
LED1_ON();
delay(500);
LED1_OFF();
delay(500);
fan_ON();
delay(500);
fan_OFF();
*/
/*
char c = getchar();
if(c == '\r'){
putchar('\r');
putchar('\n');
}
putchar(c);
if(c == 'a'){
LED1_ON();
LED2_OFF();
LED3_OFF();
}else if(c == 'b'){
LED2_ON();
LED1_OFF();
LED3_OFF();
}else{
LED3_ON();
LED1_OFF();
LED2_OFF();
}
*/
//printf("in main function\n\r");
delay(1000);
short tmp=i2c_read_tmp();
unsigned short hum=i2c_read_hum();
hum=125*hum/65536-6;
tmp=175.72*tmp/65536-46.85;
printf("hum=%d tmp=%d\n",hum,tmp);
}
return 0;
}