STM32MP157 I2C和SPI总线实验

I2C.h


#ifndef I2C_DRIVER_H
#define I2C_DRIVER_H

#include "gpio.h"

#define NACK 				1
#define ACK					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 & (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 & (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--);
	}
}

/* 初始化两个引脚 */
void I2C_Init(void)
{
	/* 使能RCC时钟 */
	SCL_PIN_CLK_EN();

    // 设置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_H();
	SDA_H();
	
}

/* 配置SDA引脚为输出 */
void I2C_SDA_OUT(void)
{
	GPIOF->MODER &= (~(0x3 << 30));
	GPIOF->MODER |= (0x1 << 30);
}

/* 配置SDA引脚为输入 */
void I2C_SDA_IN(void)
{
	GPIOF->MODER &= (~(0x3 << 30));
}

/* 开始信号 */
void I2C_Start(void)
{
	I2C_SDA_OUT();

	SCL_H();
	I2C_Delay();

	SDA_H();
	I2C_Delay();

	SDA_L();
	I2C_Delay();

	SCL_L();
	I2C_Delay();
	
}

/* I2C停止信号 */
void I2C_Stop(void)
{
	I2C_SDA_OUT();

	SCL_L();
	I2C_Delay();

	SDA_L();
	I2C_Delay();

	SCL_H();
	I2C_Delay();

	SDA_H();
	I2C_Delay();
}

/* I2C发出应答信号 */
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发出非应答信号 */
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();
	

	for(cnt=0; cnt<8; cnt++)
	{
		SCL_L();
		I2C_Delay();

		if(data & 0x80)
		{
			SDA_H();
		}
		else
		{
			SDA_L();
		}
		I2C_Delay();
		SCL_H();
		
		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;

	

	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"
// MOSI对应的引脚输出高低电平的信号
#define  MOSI_OUTPUT_H()	do{GPIOE->ODR |= (0x1 << 14);}while(0)
#define  MOSI_OUTPUT_L()    do{GPIOE->ODR &= (~(0x1 << 14));}while(0)

// 对应595芯片的锁存引脚输出高低电平
#define  NSS_OUTPUT_H()	    do{GPIOE->ODR |= (0x1 << 11);}while(0)
#define  NSS_OUTPUT_L()     do{GPIOE->ODR &= (~(0x1 << 11));}while(0)
	
// 时钟信号对应的引脚输出高低电平
#define  SCK_OUTPUT_H()     do{GPIOE->ODR |= (0x1 << 12);}while(0)
#define  SCK_OUTPUT_L()     do{GPIOE->ODR &= (~(0x1 << 12));}while(0)

static delay_us(unsigned int us);


/*
 * 函数功能: SPI初始化函数,推挽输出,高速,禁止上拉和下拉
 * 函数参数:无
 * 函数返回值:无
*/
void SPI_init(void);
/*
 * 函数功能:SPI发送数据的函数
 * 函数参数:dat : 要发送的数据
 * 函数返回值:无
 *
*/
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时钟使能 */
	RCC->MP_AHB4ENSETR |= (0x1<<4);

	/* MOSI引脚配置 */
	GPIOE->MODER &= (~(0x3 << 28));
	GPIOE->MODER |= (0x1 << 28);
	GPIOE->OTYPER &= (~(0x1 << 14));
	GPIOE->OSPEEDR &=(~(0x3 << 28));
	GPIOE->PUPDR &= (~(0x3 << 28));
	/* MISO引脚配置 */
	GPIOE->MODER &= (~(0x3 << 26));
	GPIOE->OTYPER &= (~(0x1 << 13));
	GPIOE->OSPEEDR &=(~(0x3 << 26));
	GPIOE->PUPDR &= (~(0x3 << 28));
	/* SCLK引脚配置 */
	GPIOE->MODER &= (~(0x3 << 24));
	GPIOE->MODER |= (0x1 << 24);
	GPIOE->OTYPER &= (~(0x1 << 12));
	GPIOE->OSPEEDR &=(~(0x3 << 24));
	GPIOE->PUPDR &= (~(0x3 << 24));
	/* CS引脚配置 */
	GPIOE->MODER &= (~(0x3 << 22));
	GPIOE->MODER |= (0x1 << 22);
	GPIOE->OTYPER &= (~(0x1 << 11));
	GPIOE->OSPEEDR &=(~(0x3 << 22));
	GPIOE->PUPDR &= (~(0x3 << 22));

	/* CS引脚拉低电平起始信号 */
	NSS_OUTPUT_L();
	/* SPI时钟线拉低 */
	SCK_OUTPUT_L();
	
}

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;

		/* 时钟线电平上升沿,数据写入 */
		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++);
	}
}
/*
 * 函数名:si7006_init
 * 函数功能:SI7006芯片的初始化
 * 函数参数:无
 * 函数返回值:无
*/
void si7006_init(void)
{
	I2C_Init();
	I2C_Start();
	I2C_SendByte(0x40 << 1 | 0);
	I2C_SendByte(0xE6);
	I2C_SendByte(0x3A);
	I2C_Stop();
}
/*
 * 函数名:si7006_read_hum_data
 * 函数功能:读取SI7006的湿度转换结果
 * 函数参数:
 *     slave_addr : 从机地址
 *     cmd_code : 命令码
 * 函数返回值:湿度测量的数字量
*/
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;
}
/*
 * 函数名:si7006_read_temp_data
 * 函数功能:读取SI7006的温度转换结果
 * 函数参数:
 *     slave_addr : 从机地址
 *     cmd_code : 命令码
 * 函数返回值:温度测量的数字量
*/
short si7006_read_temp_data(unsigned char slave_addr, 
		unsigned char cmd_code)
{
			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;

}


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 tem;
	short t_g;
	short t_s;
	unsigned char i;
	unsigned int j;
	
	si7006_init();
	SPI_init();
	

	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\n\r", tem);
		printf("hum = %d\n\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();
			}
		}
	}
	
	return 0;
}

效果图

在这里插入图片描述
小数点仅作为分割数字使用,两边各自是两个整数
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值