1月2日作业
2024-01-02 23:03:23
按按钮3,数码管显示湿度和温度
按按钮2,数码管显示温度
按按钮1,数码管显示湿度
main
#include "si7006.h"
#include "spi.h"
#include "key_int.h"
int num[10] = {0xFC,0x60,0xDA,0xF2,0x66,0xB6,0xbE,0xE0,0xFE,0xF6};
int main()
{
SPI_init();
key1_it_config();
key2_it_config();
key3_it_config();
unsigned short hum;
short tem;
//进行si7006的初始化
si7006_init();
while(1)
{
//读取湿度
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;
deley(1000);//延时打印
}
return 0;
}
key_int.h
#ifndef __KEY_IT_H__
#define __KEY_IT_H__
#include "stm32mp1xx_gpio.h"
#include "stm32mp1xx_gic.h"
#include "stm32mp1xx_exti.h"
#include "stm32mp1xx_rcc.h"
void delay_ms(int ms);
void key1_it_config();
void key2_it_config();
void key3_it_config();
#endif
si7006.h
#ifndef __SI7006_H__
#define __SI7006_H__
#include "iic.h"
#define SI7006_SLAVE 0x40
void si7006_init(void);
void deley(int ms);
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_H__
spi.h
#ifndef __SPI_H__
#define __SPI_H__
#include "stm32mp1xx_gpio.h"
#include "stm32mp1xx_rcc.h"
// MOSI对应的引脚输出高低电平的信号PE14
#define MOSI_OUTPUT_H() do{GPIOE->ODR |= (0x1 << 14);}while(0)
#define MOSI_OUTPUT_L() do{GPIOE->ODR &= (~(0x1 << 14));}while(0)
// 对应595芯片的锁存引脚输出高低电平 PE11
#define NSS_OUTPUT_H() do{GPIOE->ODR |= (0x1 << 11);}while(0)
#define NSS_OUTPUT_L() do{GPIOE->ODR &= (~(0x1 << 11));}while(0)
// 时钟信号对应的引脚输出高低电平 PE12
#define SCK_OUTPUT_H() do{GPIOE->ODR |= (0x1 << 12);}while(0)
#define SCK_OUTPUT_L() do{GPIOE->ODR &= (~(0x1 << 12));}while(0)
/*
* 函数功能: SPI初始化函数,推挽输出,高速,禁止上拉和下拉
* 函数参数:无
* 函数返回值:无
*/
void SPI_init(void);
/*
* 函数功能:SPI发送数据的函数
* 函数参数:dat : 要发送的数据
* 函数返回值:无
*
*/
void SPI_write(unsigned char dat);
#endif // __SPI_H__
key_int.c
#include "key_int.h"
void delay_ms(int ms)
{
int i,j;
for(i = 0; i < ms;i++)
for (j = 0; j < 1800; j++);
}
void key1_it_config()
{
//使能GPIOF时钟
RCC->MP_AHB4ENSETR |= (0x1<<5);
//设置PF9管脚为输入
GPIOF->MODER &= (~(0x3<<18));
//设置PF9作为EXTI9事件的输入
EXTI->EXTICR3 &= (~(0xff<<8));
EXTI->EXTICR3 |= (0x05<<8);
//设置下降沿使能检测EXTI9事件
EXTI->FTSR1 |= (0x1<<9);
//设置EXIT9事件不屏蔽
EXTI->C1IMR1 |= (0x1<<9);
//GICD使能EXTI9(99号)中断
GICD->ISENABLER[3] |= (0x1<<3);
//GICD设置99号中断的优先级
GICD->IPRIORITYR[24] &= (~(0x1f<<27));
//选择器CPU0处理当前中断
GICD->ITARGETSR[24] |= (0x1<<24);
//全局使能组0中断被转发到GICC
GICD->CTRL |= (0x1);
//设置中断的优先级掩码
GICC->PMR |= (0x1f<<3);
//允许组0中断被CPU处理
GICC->CTRL |= (0x1);
}
void key2_it_config()
{
//使能GPIOF时钟
//RCC->MP_AHB4ENSETR |= (0x1<<5);
//设置PF7管脚为输入
GPIOF->MODER &= (~(0x3<<14));
//设置PF7作为EXTI7事件的输入
EXTI->EXTICR2 &= (~(0xff<<24));
EXTI->EXTICR2 |= (0x05<<24);
//设置下降沿使能检测EXTI7事件
EXTI->FTSR1 |= (0x1<<7);
//设置EXIT7事件不屏蔽
EXTI->C1IMR1 |= (0x1<<7);
//GICD使能EXTI7(97号)中断
GICD->ISENABLER[3] |= (0x1<<1);
//GICD设置97号中断的优先级
GICD->IPRIORITYR[24] &= (~(0x1f<<11));
//选择器CPU0处理当前中断
GICD->ITARGETSR[24] |= (0x1<<8);
//全局使能组0中断被转发到GICC
GICD->CTRL |= (0x1);
//设置中断的优先级掩码
GICC->PMR |= (0x1f<<3);
//允许组0中断被CPU处理
GICC->CTRL |= (0x1);
}
void key3_it_config()
{
//使能GPIOF时钟
//RCC->MP_AHB4ENSETR |= (0x1<<5);
//设置PF8管脚为输入
GPIOF->MODER &= (~(0x3<<16));
//设置PF8作为EXTI8事件的输入
EXTI->EXTICR3 &= (~(0xff));
EXTI->EXTICR3 |= (0x05);
//设置下降沿使能检测EXTI8事件
EXTI->FTSR1 |= (0x1<<8);
//设置EXIT8事件不屏蔽
EXTI->C1IMR1 |= (0x1<<8);
//GICD使能EXTI8(98号)中断
GICD->ISENABLER[3] |= (0x1<<2);
//GICD设置98号中断的优先级
GICD->IPRIORITYR[24] &= (~(0x1f<<19));
//选择器CPU0处理当前中断
GICD->ITARGETSR[24] |= (0x1<<16);
//全局使能组0中断被转发到GICC
GICD->CTRL |= (0x1);
//设置中断的优先级掩码
GICC->PMR |= (0x1f<<3);
//允许组0中断被CPU处理
GICC->CTRL |= (0x1);
}
si7006.c
#include "iic.h"
#include "si7006.h"
void deley(int ms)
{
int i,j;
for(i=0;i<ms;i++)
{
for(j=0;j<2000;j++);
}
}
/*
* 函数名:si7006_init
* 函数功能:SI7006芯片的初始化
* 函数参数:无
* 函数返回值:无
*/
//往SI7006芯片0XE6写入0X3A
void si7006_init(void)
{
//I2初始化
i2c_init();
//发送起始信号
i2c_start();
//主机发送7位从机地址+1位写位
i2c_write_byte(0X40<<1|0);
//等待从机回应
i2c_wait_ack();
//发送寄存器地址
i2c_write_byte(0XE6);
//等待从机回应
i2c_wait_ack();
//发送要写的数据
i2c_write_byte(0X3A);
//等待从机回应
i2c_wait_ack();
//发送终止信号
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 dat;//保存读取到的湿度数据
unsigned char dat_h,dat_l;//保存读取到的数据的高八位和低八位
//发送起始信号
i2c_start();
//主机发送7位从机地址+1位写位
i2c_write_byte(slave_addr<<1|0);
//等待从机回应
i2c_wait_ack();
//发送寄存器地址
i2c_write_byte(cmd_code);
//等待从机回应
i2c_wait_ack();
//发送第二次起始信号
i2c_start();
//主机发送7位从机地址+1位读位
i2c_write_byte(slave_addr<<1|1);
//等待从机回应
i2c_wait_ack();
//延时等待从机测量数据
deley(100);
//读取数据的高8位
dat_h=i2c_read_byte(0);//读取完毕发送应答信号
//读取数据的低8位
dat_l=i2c_read_byte(1);//读取完毕发送非应答信号
//发送停止信号
i2c_stop();
//将读取到的数据整合到一起
dat=(dat_h<<8)|dat_l;
return dat;
}
/*
* 函数名:si7006_read_temp_data
* 函数功能:读取SI7006的温度转换结果
* 函数参数:
* slave_addr : 从机地址
* cmd_code : 命令码 寄存器地址
* 函数返回值:温度测量的数字量
*/
short si7006_read_temp_data(unsigned char slave_addr,
unsigned char cmd_code)
{
short dat;//保存读取到的温度数据
char dat_h,dat_l;//保存读取到的数据的高八位和低八位
//发送起始信号
i2c_start();
//主机发送7位从机地址+1位写位
i2c_write_byte(slave_addr<<1|0);
//等待从机回应
i2c_wait_ack();
//发送寄存器地址
i2c_write_byte(cmd_code);
//等待从机回应
i2c_wait_ack();
//发送第二次起始信号
i2c_start();
//主机发送7位从机地址+1位写位
i2c_write_byte(slave_addr<<1|1);
//等待从机回应
i2c_wait_ack();
//延时等待从机测量数据
deley(100);
//读取数据的高8位
dat_h=i2c_read_byte(0);//读取完毕发送应答信号
//读取数据的低8位
dat_l=i2c_read_byte(1);//读取完毕发送非应答信号
//发送停止信号
i2c_stop();
//将读取到的数据整合到一起
dat=(dat_h<<8)|dat_l;
return dat;
}
spi.c
#include"spi.h"
void delay_us1(unsigned int us)
{
int i,j;
for(i=0;i<us;i++)
{
for(j=0;j<1;j++);
}
}
void SPI_init(void)
{
//1.使能GPIOE时钟
RCC->MP_AHB4ENSETR |= (0x1<<4);
//2.MOSI管脚PE14 设置输出的属性
GPIOE->MODER &= (~(0x3<<28));
GPIOE->MODER |= (0x1<<28);
GPIOE->OTYPER &= (~(0x1<<14));
GPIOE->OSPEEDR &= (~(0x3<<28));
GPIOE->PUPDR &= (~(0x3<<28));
//3.MISO管脚PE13 设置输入的属性
GPIOE->MODER &= (~(0x3<<26));
GPIOE->MODER |= (0x1<<26);
GPIOE->OTYPER &= (~(0x1<<13));
GPIOE->OSPEEDR &= (~(0x3<<26));
GPIOE->PUPDR &= (~(0x3<<26));
//4.SCK管脚PE12 设置输出的属性
GPIOE->MODER &= (~(0x3<<24));
GPIOE->MODER |= (0x1<<24);
GPIOE->OTYPER &= (~(0x1<<12));
GPIOE->OSPEEDR &= (~(0x3<<24));
GPIOE->PUPDR &= (~(0x3<<24));
//5.RCK(NSS)管脚 设置输出的属性
GPIOE->MODER &= (~(0x3<<22));
GPIOE->MODER |= (0x1<<22);
GPIOE->OTYPER &= (~(0x1<<11));
GPIOE->OSPEEDR &= (~(0x3<<22));
GPIOE->PUPDR &= (~(0x3<<22));
//默认PE12和PE11输出低电平,方便产生上升沿
NSS_OUTPUT_L();
SCK_OUTPUT_L();
}
void SPI_write(unsigned char dat)
{
unsigned int i;
for(i=0;i<8;i++)
{
if(dat&0X01)
{
MOSI_OUTPUT_H();
//输出高电平
}
else
{
MOSI_OUTPUT_L();
//输出低电平
}
dat >>= 1;
//产生上升沿
SCK_OUTPUT_L();
delay_us1(10);
SCK_OUTPUT_H();
delay_us1(10);
}
}
do_irq.c
#include "key_int.h"
#include "uart4.h"
#include "si7006.h"
#include "spi.h"
extern void printf(const char *fmt, ...);
unsigned int i = 0;
void do_irq(void)
{
int num[10] = {0xFC,0x60,0xDA,0xF2,0x66,0xB6,0xbE,0xE0,0xFE,0xF6};
int irqno = (GICC->IAR & 0x3ff);
unsigned short hum;
short tem;
//读取湿度
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;
deley(1000);//延时打印
int i= 500;
switch (irqno)
{
case 99: //key1
while(i--)
{
//将获取到的数据打印到串口
SPI_write(0x80); // 发送数码管的位
SPI_write(num[hum/10]); // 发送数码管的段
delay_ms(1);
NSS_OUTPUT_L();
delay_ms(1);
NSS_OUTPUT_H(); // 锁存的时钟从低到高的变化
// 将移位寄存器中的数据锁存到锁存寄存器中
delay_ms(1);
SPI_write(0x40); // 发送数码管的位
SPI_write(num[hum%10]); // 发送数码管的段
//delay_ms(1);
delay_ms(1);
NSS_OUTPUT_L();
delay_ms(1);
NSS_OUTPUT_H(); // 锁存的时钟从低到高的变化
// 将移位寄存器中的数据锁存到锁存寄存器中
delay_ms(1);
}
//GPIOE->ODR |= (0x1<<10);
puts("hum_on\r\n");
//清除GICD的中断排队标志
GICD->ICPENDR[3] |= (0x1<<3);
//清除exti的事件触发标志
EXTI->FPR1 |= (0x1<<9);
break;
case 97: //key2
while(i--)
{
SPI_write(0x20); // 发送数码管的位
SPI_write(num[tem/10]); // 发送数码管的段
//delay_ms(1);
delay_ms(1);
NSS_OUTPUT_L();
delay_ms(1);
NSS_OUTPUT_H(); // 锁存的时钟从低到高的变化
// 将移位寄存器中的数据锁存到锁存寄存器中
delay_ms(1);
SPI_write(0x10); // 发送数码管的位
SPI_write(num[tem%10]); // 发送数码管的段
//delay_ms(1);
delay_ms(1);
NSS_OUTPUT_L();
delay_ms(1);
NSS_OUTPUT_H(); // 锁存的时钟从低到高的变化
// 将移位寄存器中的数据锁存到锁存寄存器中
delay_ms(1);
}
puts("tem_on\r\n");
//清除GICD的中断排队标志
GICD->ICPENDR[3] |= (0x1<<1);
//清除exti的事件触发标志
EXTI->FPR1 |= (0x1<<7);
break;
case 98: //key3
while(i--)
{
//将获取到的数据打印到串口
SPI_write(0x80); // 发送数码管的位
SPI_write(num[hum/10]); // 发送数码管的段
delay_ms(1);
NSS_OUTPUT_L();
delay_ms(1);
NSS_OUTPUT_H(); // 锁存的时钟从低到高的变化
// 将移位寄存器中的数据锁存到锁存寄存器中
delay_ms(1);
SPI_write(0x40); // 发送数码管的位
SPI_write(num[hum%10]); // 发送数码管的段
//delay_ms(1);
delay_ms(1);
NSS_OUTPUT_L();
delay_ms(1);
NSS_OUTPUT_H(); // 锁存的时钟从低到高的变化
// 将移位寄存器中的数据锁存到锁存寄存器中
delay_ms(1);
SPI_write(0x20); // 发送数码管的位
SPI_write(num[tem/10]); // 发送数码管的段
//delay_ms(1);
delay_ms(1);
NSS_OUTPUT_L();
delay_ms(1);
NSS_OUTPUT_H(); // 锁存的时钟从低到高的变化
// 将移位寄存器中的数据锁存到锁存寄存器中
delay_ms(1);
SPI_write(0x10); // 发送数码管的位
SPI_write(num[tem%10]); // 发送数码管的段
//delay_ms(1);
delay_ms(1);
NSS_OUTPUT_L();
delay_ms(1);
NSS_OUTPUT_H(); // 锁存的时钟从低到高的变化
// 将移位寄存器中的数据锁存到锁存寄存器中
delay_ms(1);
}
puts("hum_tem_on\r\n");
//清除GICD的中断排队标志
GICD->ICPENDR[3] |= (0x1<<2);
//清除exti的事件触发标志
EXTI->FPR1 |= (0x1<<8);
break;
}
//清除中断号
GICC->EOIR = irqno;
}
效果演示
文章来源:https://blog.csdn.net/m0_56986240/article/details/135344465
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!