目录
iic.h
iic.c
ap3216c.h
ap3216.c
main.c
实验效果
iic.h
#ifndef __IIC_H__
#define __IIC_H__#include "stm32mp1xx_gpio.h"
#include "stm32mp1xx_rcc.h"
//SDA 数据线为PF15
//SCL 时钟线为PF14//配置PF15为输出模式
#define SET_SDA_OUT do{GPIOF->MODER &=(~(0x3<<30));\GPIOF->MODER |=(0x1<<30);}while(0)//配置PF15为输入模式
#define SET_SDA_IN do{GPIOF->MODER &=(~(0x3<<30));}while(0)//读取PF15输入寄存器的值
#define I2C_SDA_READ GPIOF->IDR & (0x1<<15)//PF14输出高电平、低电平
#define I2C_SCL_H do{GPIOF->BSRR |= (0x1<<14);}while(0)
#define I2C_SCL_L do{GPIOF->BRR |= (0x1<<14);}while(0)//PF15输入高电平、低电平
#define I2C_SDA_H do{GPIOF->BSRR |= (0x1<<15);}while(0)
#define I2C_SDA_L do{GPIOF->BRR |= (0x1<<15);}while(0)void delay_us(void);
//模拟I2C
void i2c_init(void);
void i2c_start(void);
void i2c_stop(void);
void i2c_write_byte(unsigned char dat);
unsigned char i2c_read_byte(unsigned char ack);
unsigned char i2c_wait_ack(void);
void i2c_ack(void);
void i2c_nack(void);#endif
iic.c
#include "iic.h"//微妙级的延时
void delay_us(void){unsigned int i=2000;while(i--);
}
//模拟I2C//I2C初始化
void i2c_init(void){//GPIOF时钟使能RCC->MP_AHB4ENSETR |= (0x1<<5);//配置PF14、PF15为输出模式GPIOF->MODER &= (~(0xF<<28));GPIOF->MODER |= (0x5<<28);//配置PF14、PF15为推挽输出GPIOF->OTYPER &= (~(0x3<<14));//配置PF14、PF15输出速度为超高速GPIOF->OSPEEDR |= (0xF<<28);//配置PF14、PF15无上拉下拉GPIOF->PUPDR &= (~(0xF<<28));//将SCL和SDA输出高电平I2C_SCL_H;I2C_SDA_H;}//发送起始信号
void i2c_start(void){//设置SDA为输出模式SET_SDA_OUT;//拉高数据线和时钟线I2C_SCL_H;I2C_SDA_H;delay_us(); //延时//拉低数据线I2C_SDA_L;delay_us(); //延时//拉低时钟线I2C_SCL_L;}//发送停止信号
void i2c_stop(void){//设置SDA为输出模式SET_SDA_OUT;//拉低时钟线I2C_SCL_L;delay_us();delay_us();//修改数据线为低电平I2C_SDA_L;delay_us();//拉高时钟线I2C_SCL_H;delay_us();//拉高数据线I2C_SDA_H;}//发送数据
void i2c_write_byte(unsigned char dat){unsigned int i;//PF14配置为输出模式SET_SDA_OUT;for(i=0;i<8;i++){//拉低时钟线I2C_SCL_L;delay_us();//修改数据线的值if(dat&(0x1<<7)){I2C_SDA_H;}else{I2C_SDA_L;}delay_us();//拉高时钟线I2C_SCL_H;delay_us(); //拉高是时钟线后延时 delay_us(); //延时等待从机读取dat<<=1;}
}//读取数据
unsigned char i2c_read_byte(unsigned char ack){//配置为输入模式SET_SDA_IN;unsigned char data;for(unsigned int i=0;i<8;i++){//从机需要向寄存器写入数据//所有需要拉低时钟线I2C_SCL_L;delay_us(); //延时delay_us(); //等待从机写入数据//拉高时钟线读取数据I2C_SCL_H;delay_us(); //延时data<<=1;if(I2C_SDA_READ){data|=0x1; }else data|=0x0;}if(!ack){i2c_nack();}else{i2c_ack();}//返回读取的数值return data;
}//等带从机ack
unsigned char i2c_wait_ack(void){//拉低时钟线,修改SDA电平I2C_SCL_L;delay_us();I2C_SDA_H; //释放给从机delay_us();//SDA配置为输入模式SET_SDA_IN;delay_us();delay_us();//拉高时钟线读取从机ackI2C_SCL_H;delay_us();if(I2C_SDA_READ){return 1;}I2C_SCL_L;return 0;
} //ack应答
void i2c_ack(void){//配置为输出模式SET_SDA_OUT;//拉低时钟线I2C_SCL_L;delay_us();//拉低数据线I2C_SDA_L;delay_us();//拉高时钟线I2C_SCL_H;delay_us();delay_us();//拉低时钟线?I2C_SCL_L;
}//非ack应答
void i2c_nack(void){//配置为输出模式SET_SDA_OUT;//拉低时钟线I2C_SCL_L;delay_us();//拉高数据线I2C_SDA_H;delay_us();//拉高时钟线I2C_SCL_H;delay_us();delay_us();//拉低时钟线?I2C_SCL_L;}
ap3216c.h
#ifndef __AP3216C_H__
#define __AP3216C_H__//ap3216c初始化
void ap3216c_init();
void ap3216c_init1();
//读取ap3216c环境光
unsigned char ap3216c_read_alsl();
unsigned char ap3216c_read_alsh();#endif
ap3216.c
#include "ap3216c.h"
#include "iic.h"
//ap3216c初始化
void ap3216c_init(){//发送起始信号i2c_start();//发送七位从机地址+1位写标志 0x1E | 0x0 = 0x3ci2c_write_byte(0x3c);//等待从机应答i2c_wait_ack();//发送8位寄存器地址0x00i2c_write_byte(0x00);//等待从机应答i2c_wait_ack();//写入数据0x3A,si7006初始值i2c_write_byte(0x1);//等待应答i2c_wait_ack();//发送停止信号 i2c_stop();
}//读取ap3216c环境光
unsigned char ap3216c_read_alsl(){//发送起始信号i2c_start();//发送七位从机地址+1位写标志 0x1E | 0x0 = 0x3Ci2c_write_byte(0x3C);//等待从机应答i2c_wait_ack();//发送8位寄存器地址0xE3i2c_write_byte(0x0C);//等待从机应答i2c_wait_ack();//发送重复开始信号i2c_start();//发送从机地址和读写标志 0x40 | 0x1 = 0x81i2c_write_byte(0x3D);//等待从机应答i2c_wait_ack();//读取环境光char als_l;als_l=i2c_read_byte(1);//发送应答//发送停止信号i2c_stop();return als_l;}
//读取ap3216c环境光
unsigned char ap3216c_read_alsh(){//发送起始信号i2c_start();//发送七位从机地址+1位写标志 0x1E | 0x0 = 0x3Ci2c_write_byte(0x3C);//等待从机应答i2c_wait_ack();//发送8位寄存器地址0xE3i2c_write_byte(0x0D);//等待从机应答i2c_wait_ack();//发送重复开始信号i2c_start();//发送从机地址和读写标志 0x40 | 0x1 = 0x81i2c_write_byte(0x3D);//等待从机应答i2c_wait_ack();//读取环境光char als_h;als_h=i2c_read_byte(1);//发送应答//发送停止信号i2c_stop();return als_h;}
main.c
#include "gpio.h"
#include "led.h"
#include "uart4.h"
#include "keyip.h"
#include "iic.h"
#include "si7006.h"
#include "ap3216c.h"
extern void printf(const char *fmt, ...);
int main()
{led1_init();i2c_init();ap3216c_init();unsigned short als;unsigned char als_l;unsigned char als_h;while (1){als_l=ap3216c_read_alsl(1);als_h=ap3216c_read_alsh(1);als=((unsigned short)als_h<<8) | als_l;printf("als=%d\n",als);if(als<100){led1_ctl(1);}else{led1_ctl(0);}delay(1000);}return 0;
}
实验效果