I2C.h
#ifndef I2C_DRIVER_H #define I2C_DRIVER_H #include "gpio.h" #define NACK 1 #defineACK 0 #define SCL_PIN 14 #define SCL_PORT GPIOF #define SCL_PIN_CLK_EN() do{<!-- -->RCC->MP_AHB4ENSETR |= (0x1 << 5);}while(0) #define SDA_PIN 15 #define SDA_PORT GPIOF #define SDA_PIN_CLK_EN() do{<!-- -->RCC->MP_AHB4ENSETR |= (0x1 << 5);}while(0) #define SCL_H() do{<!-- -->GPIOF->BSRR |= (0x1 << 14);}while(0) #define SCL_L() do{<!-- -->GPIOF->BRR |= (0x1 << 14);}while(0) #define SCL_INPUT() (GPIOF->IDR & amp; (0x1 << 14)) #define SDA_H() do{<!-- -->GPIOF->BSRR |= (0x1 << 15);}while(0) #define SDA_L() do{<!-- -->GPIOF->BRR |= (0x1 << 15);}while(0) #define SDA_INPUT() (GPIOF->IDR & amp; (0x1 << 15)) #define I2C_Delay() us_timer_delay(10) void us_timer_delay(unsigned short t); void I2C_Init(void); void I2C_SDA_OUT(void); void I2C_SDA_IN(void); void I2C_Start(void); void I2C_Stop(void); void I2C_ACK(void); void I2C_NACK(void); unsigned char I2C_GetACK(void); void I2C_SendByte(unsigned char data); unsigned char I2C_ReadByte(unsigned char ack); #endif
I2C.C
#include "i2c_driver.h" void us_timer_delay(unsigned short t) {<!-- --> unsigned short counter = 0; while(t--) {<!-- --> counter=10; while(counter--); } } /* Initialize two pins */ void I2C_Init(void) {<!-- --> /* Enable RCC clock */ SCL_PIN_CLK_EN(); //Set the PF14 and PF15 pins as general output functions GPIOF->MODER & amp;= (~(0xF << 28)); GPIOF->MODER |= (0x5 << 28); //Set the PF14 and PF15 pins as push-pull outputs GPIOF->OTYPER & amp;= (~(0x3 << 14)); //Set the PF14 and PF15 pins as high-speed outputs GPIOF->OSPEEDR |= (0xF << 28); //Set the disable pull-up and pull-down of PF14 and PF15 pins GPIOF->PUPDR & amp;= (~(0xF << 28)); /* Pull the pin level up */ SCL_H(); SDA_H(); \t } /* Configure the SDA pin as output */ void I2C_SDA_OUT(void) {<!-- --> GPIOF->MODER & amp;= (~(0x3 << 30)); GPIOF->MODER |= (0x1 << 30); } /* Configure the SDA pin as input */ void I2C_SDA_IN(void) {<!-- --> GPIOF->MODER & amp;= (~(0x3 << 30)); } /* start signal */ void I2C_Start(void) {<!-- --> I2C_SDA_OUT(); SCL_H(); I2C_Delay(); SDA_H(); I2C_Delay(); SDA_L(); I2C_Delay(); SCL_L(); I2C_Delay(); \t } /* I2C stop signal */ void I2C_Stop(void) {<!-- --> I2C_SDA_OUT(); SCL_L(); I2C_Delay(); SDA_L(); I2C_Delay(); SCL_H(); I2C_Delay(); SDA_H(); I2C_Delay(); } /* I2C sends a response signal */ void I2C_ACK(void) {<!-- --> I2C_SDA_OUT(); SCL_L(); I2C_Delay(); SDA_L(); I2C_Delay(); SCL_H(); I2C_Delay(); I2C_Delay(); SCL_L(); I2C_Delay(); } /* I2C sends a non-response signal */ void I2C_NACK(void) {<!-- --> I2C_SDA_OUT(); SCL_L(); I2C_Delay(); SDA_H(); I2C_Delay(); SCL_H(); I2C_Delay(); I2C_Delay(); SCL_L(); I2C_Delay(); } unsigned char I2C_GetACK(void) {<!-- --> unsigned char time = 0; SDA_H(); SCL_L(); I2C_Delay(); I2C_SDA_IN(); I2C_Delay(); I2C_Delay(); SCL_H(); I2C_Delay(); while (SDA_INPUT()) {<!-- --> time + + ; if(time>250) {<!-- --> SCL_L(); return 1; } } SCL_L(); return 0; } void I2C_SendByte(unsigned char data) {<!-- --> unsigned int cnt = 0; I2C_SDA_OUT(); \t for(cnt=0; cnt<8; cnt + + ) {<!-- --> SCL_L(); I2C_Delay(); if(data & 0x80) {<!-- --> SDA_H(); } else {<!-- --> SDA_L(); } I2C_Delay(); SCL_H(); \t\t I2C_Delay(); I2C_Delay(); data = data<<1; I2C_Delay(); } SCL_L(); I2C_Delay(); I2C_GetACK(); } unsigned char I2C_ReadByte(unsigned char ack) {<!-- --> unsigned int cnt; unsigned char data = 0xff; \t for(cnt=0; cnt<8; cnt + + ) {<!-- --> SCL_L(); I2C_Delay(); I2C_Delay(); SCL_H(); I2C_Delay(); data <<= 1; if(SDA_INPUT()) {<!-- --> data |= 0x01; } I2C_Delay(); } if(ack == 0) {<!-- --> I2C_ACK(); } else {<!-- --> I2C_NACK(); } return data; }
SPI.h
#ifndef __SPI_H__ #define __SPI_H__ #include "stm32mp1xx_gpio.h" #include "stm32mp1xx_rcc.h" //The pin corresponding to MOSI outputs high and low level signals #define MOSI_OUTPUT_H() do{<!-- -->GPIOE->ODR |= (0x1 << 14);}while(0) #define MOSI_OUTPUT_L() do{<!-- -->GPIOE->ODR & amp;= (~(0x1 << 14));}while(0) // Corresponds to the latch pin of the 595 chip outputting high and low levels #define NSS_OUTPUT_H() do{<!-- -->GPIOE->ODR |= (0x1 << 11);}while(0) #define NSS_OUTPUT_L() do{<!-- -->GPIOE->ODR & amp;= (~(0x1 << 11));}while(0) \t //The pin corresponding to the clock signal outputs high and low levels #define SCK_OUTPUT_H() do{<!-- -->GPIOE->ODR |= (0x1 << 12);}while(0) #define SCK_OUTPUT_L() do{<!-- -->GPIOE->ODR & amp;= (~(0x1 << 12));}while(0) static delay_us(unsigned int us); /* * Function: SPI initialization function, push-pull output, high speed, pull-up and pull-down disabled * Function parameters: none * Function return value: None */ void SPI_init(void); /* * Function: SPI function to send data * Function parameters: dat: data to be sent * Function return value: None * */ void SPI_write(unsigned char dat); #endif // __SPI_H__
SPI.c
#include "spi.h" /* SPI4_NSS PE11 SPI4_SCK PE12 SPI4_MOSI PE14 SPI4_MISO PE13 */ static delay_us(unsigned int us) {<!-- --> int i = 0; int j = 0; for(i=0; i<us; i + + ) {<!-- --> for(j=0; j<10;j + + ); } } void SPI_init(void) {<!-- --> /* RCC clock enable */ RCC->MP_AHB4ENSETR |= (0x1<<4); /* MOSI pin configuration */ GPIOE->MODER & amp;= (~(0x3 << 28)); GPIOE->MODER |= (0x1 << 28); GPIOE->OTYPER & amp;= (~(0x1 << 14)); GPIOE->OSPEEDR & amp;=(~(0x3 << 28)); GPIOE->PUPDR & amp;= (~(0x3 << 28)); /* MISO pin configuration */ GPIOE->MODER & amp;= (~(0x3 << 26)); GPIOE->OTYPER & amp;= (~(0x1 << 13)); GPIOE->OSPEEDR & amp;=(~(0x3 << 26)); GPIOE->PUPDR & amp;= (~(0x3 << 28)); /* SCLK pin configuration */ GPIOE->MODER & amp;= (~(0x3 << 24)); GPIOE->MODER |= (0x1 << 24); GPIOE->OTYPER & amp;= (~(0x1 << 12)); GPIOE->OSPEEDR & amp;=(~(0x3 << 24)); GPIOE->PUPDR & amp;= (~(0x3 << 24)); /* CS pin configuration */ GPIOE->MODER & amp;= (~(0x3 << 22)); GPIOE->MODER |= (0x1 << 22); GPIOE->OTYPER & amp;= (~(0x1 << 11)); GPIOE->OSPEEDR & amp;=(~(0x3 << 22)); GPIOE->PUPDR & amp;= (~(0x3 << 22)); /* CS pin pulls low level start signal */ NSS_OUTPUT_L(); /* Pull the SPI clock line low */ SCK_OUTPUT_L(); \t } void SPI_write(unsigned char dat) {<!-- --> unsigned char i; for(i=0; i<8; i + + ) {<!-- --> if(dat & 0x01) {<!-- --> MOSI_OUTPUT_H(); } else {<!-- --> MOSI_OUTPUT_L(); } dat>>=1; /* The rising edge of the clock line level, data is written */ SCK_OUTPUT_L(); delay_us(5); SCK_OUTPUT_H(); delay_us(5); } }
SI7006.h
#ifndef SI7006_H #define SI7006_H #include "i2c_driver.h" void delay_ms(unsigned int ms); void si7006_init(void); unsigned short si7006_read_hum_data(unsigned char slave_addr, unsigned char cmd_code); short si7006_read_temp_data(unsigned char slave_addr, unsigned char cmd_code); #endif
SI7006.c
#include "i2c_driver.h" #include "si7006.h" void delay_ms(unsigned int ms) {<!-- --> unsigned int i = 0; unsigned int j = 0; for(i=0; i<ms; i + + ) {<!-- --> for(j=0; j<2000; j + + ); } } /* * Function name: si7006_init * Function: initialization of SI7006 chip * Function parameters: none * Function return value: None */ void si7006_init(void) {<!-- --> I2C_Init(); I2C_Start(); I2C_SendByte(0x40 << 1 | 0); I2C_SendByte(0xE6); I2C_SendByte(0x3A); I2C_Stop(); } /* * Function name: si7006_read_hum_data * Function: Read the humidity conversion result of SI7006 * Function parameters: * slave_addr: slave address * cmd_code: command code * Function return value: digital quantity of humidity measurement */ unsigned short si7006_read_hum_data(unsigned char slave_addr, unsigned char cmd_code) {<!-- --> unsigned short data; unsigned char d_h; unsigned char d_l; I2C_Start(); I2C_SendByte(slave_addr << 1 | 0); I2C_SendByte(cmd_code); I2C_Start(); I2C_SendByte(slave_addr << 1 | 1); delay_ms(2000); d_h = I2C_ReadByte(ACK); d_l = I2C_ReadByte(NACK); I2C_Stop(); data = (d_h<<8)|d_l; return data; } /* * Function name: si7006_read_temp_data * Function: Read the temperature conversion result of SI7006 * Function parameters: * slave_addr: slave address * cmd_code: command code * Function return value: digital quantity of temperature measurement */ short si7006_read_temp_data(unsigned char slave_addr, unsigned char cmd_code) {<!-- --> short data; unsigned char d_h; unsigned char d_l; \t\t I2C_Start(); I2C_SendByte(slave_addr << 1 | 0); I2C_SendByte(cmd_code); I2C_Start(); I2C_SendByte(slave_addr << 1 | 1); delay_ms(2000); d_h = I2C_ReadByte(ACK); d_l = I2C_ReadByte(NACK); I2C_Stop(); data = (d_h<<8)|d_l; \t\t\t \t\t\t return data; }
main.c
#include "key_it.h" #include "uart.h" #include "beep.h" #include "si7006.h" #include "spi.h" void delay(volatile unsigned int d) {<!-- --> int i,j; for(i = 0; i < d;i + + ) for (j = 0; j < 1800; j + + ); } static int num[10] = {<!-- -->0xFC,0x60,0xDA,0xF2,0x66,0xB6,0xBE,0xE0,0xFE,0xF6}; static int data[5] = {<!-- -->0}; int main(void) {<!-- --> unsigned short hum; unsigned short h_g; unsigned short h_s; short term; short t_g; short t_s; unsigned char i; unsigned int j; \t si7006_init(); SPI_init(); \t while(1) {<!-- --> j = 800; hum = si7006_read_hum_data(0x40, 0xE5); tem = si7006_read_temp_data(0x40, 0xE3); hum = 125*hum/65536-6; tem = 175.72*tem/65536-46.85; h_s = hum / 10; h_g = hum % 10; t_s = tem / 10; t_g = tem % 10; data[0] = num[t_s]; data[1] = num[t_g] + 1; data[2] = num[h_s]; data[3] = num[h_g]; printf("tem = %d\ \r", tem); printf("hum = %d\ \r", hum); while(j--) {<!-- --> for(i = 0; i < 5; i + + ) {<!-- --> SPI_write(0x80 >> i); SPI_write(data[i]); NSS_OUTPUT_L(); delay_ms(1); NSS_OUTPUT_H(); } } } \t return 0; }
Renderings
The decimal point is only used to divide numbers, and there are two integers on both sides