STM32MP157 I2C and SPI bus experiment

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