完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
电子发烧友论坛|
|
|
相关推荐
1个回答
|
|
|
一、STM32CubeMX工程配置
说明:本例程采用模拟IIC,所以需要把相应IO配置为推完输出,默认为高电平 二、程序&说明 1.模拟IIC程序 myiic.c #include "myiic.h" #include "delay.h" //产生IIC起始信号 void IIC_Start(void) { SDA_OUT(); //sda线输出 IIC_SDA(1); IIC_SCL(1); delay_us(4); IIC_SDA(0);//START:when CLK is high,DATA change form high to low delay_us(4); IIC_SCL(0);//钳住I2C总线,准备发送或接收数据 } //产生IIC停止信号 void IIC_Stop(void) { SDA_OUT();//sda线输出 IIC_SCL(0); IIC_SDA(0);//STOP:when CLK is high DATA change form low to high delay_us(4); IIC_SCL(1); IIC_SDA(1);//发送I2C总线结束信号 delay_us(4); } //等待应答信号到来 //返回值:1,接收应答失败 // 0,接收应答成功 uint8_t IIC_Wait_Ack(void) { uint8_t ucErrTime=0; SDA_IN(); //SDA设置为输入 IIC_SDA(1);delay_us(1); IIC_SCL(1);delay_us(1); while(READ_SDA) { ucErrTime++; if(ucErrTime>250) { IIC_Stop(); return 1; } } IIC_SCL(0);//时钟输出0 return 0; } //产生ACK应答 void IIC_Ack(void) { IIC_SCL(0); SDA_OUT(); IIC_SDA(0); delay_us(2); IIC_SCL(1); delay_us(2); IIC_SCL(0); } //不产生ACK应答 void IIC_NAck(void) { IIC_SCL(0); SDA_OUT(); IIC_SDA(1); delay_us(2); IIC_SCL(1); delay_us(2); IIC_SCL(0); } //IIC发送一个字节 //返回从机有无应答 //1,有应答 //0,无应答 void IIC_Send_Byte(uint8_t txd) { uint8_t t; SDA_OUT(); IIC_SCL(0);//拉低时钟开始数据传输 for(t=0;t<8;t++) { IIC_SDA((txd&0x80)>>7); txd<<=1; delay_us(2); //对TEA5767这三个延时都是必须的 IIC_SCL(1); delay_us(2); IIC_SCL(0); delay_us(2); } } //读1个字节,ack=1时,发送ACK,ack=0,发送nACK uint8_t IIC_Read_Byte(unsigned char ack) { unsigned char i,receive=0; SDA_IN();//SDA设置为输入 for(i=0;i<8;i++ ) { IIC_SCL(0); delay_us(2); IIC_SCL(1); receive<<=1; if(READ_SDA)receive++; delay_us(1); } if (!ack) IIC_NAck();//发送nACK else IIC_Ack(); //发送ACK return receive; } myiic.h #ifndef _MYIIC_H #define _MYIIC_H #include "delay.h" #include "main.h" //IO方向设置 #define SDA_IN() {GPIOB->CRH&=0XFFFFFFF0;GPIOB->CRH|=(uint32_t)8<<0;} //PB7输入模式 #define SDA_OUT() {GPIOB->CRH&=0XFFFFFFF0;GPIOB->CRH|=(uint32_t)3<<0;} //PB7输出模式 //IO操作 #define IIC_SCL(n) (n ? HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET) : HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET)) //SCL #define IIC_SDA(n) (n ? HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET) : HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET)) //SDA #define READ_SDA HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_8) //输入SDA //IIC所有操作函数 void IIC_Init(void); //初始化IIC的IO口(无需调用) void IIC_Start(void); //发送IIC开始信号 void IIC_Stop(void); //发送IIC停止信号 void IIC_Send_Byte(uint8_t txd); //IIC发送一个字节 uint8_t IIC_Read_Byte(unsigned char ack);//IIC读取一个字节 uint8_t IIC_Wait_Ack(void); //IIC等待ACK信号 void IIC_Ack(void); //IIC发送ACK信号 void IIC_NAck(void); //IIC不发送ACK信号 void IIC_Write_One_Byte(uint8_t daddr,uint8_t addr,uint8_t data); uint8_t IIC_Read_One_Byte(uint8_t daddr,uint8_t addr); #endif 以上底层是基于STM32F103,若要使用在STM32其他系列上请自行移植 提示:需要修改delay.h和delay.c文件,注意时序,并且更改myiic.h中的引脚配置,如下图(注::F4和F1的IO方向设置寄存器不一样,请自行查看数据手册进行修改) 2,SHT3x底层 sht3x.c #include "sht3x.h" #include "myiic.h" _TW data_process; //定义温湿度结构体 static void SHT3x_WriteCommand(uint16_t COMMAND); //SHT30命令写入 void SHT3x_Init(void) //SHT30初始化 { IIC_Start(); IIC_Send_Byte(SHTx_Device_ADDR << 1 | Write_DATA); //写入地址和写命令 SHT3x_WriteCommand(PERI_HIGH_1_CMD); //设置为周期读取频率为1hz IIC_Stop(); } static void SHT3x_WriteCommand(uint16_t COMMAND) //SHT30命令写入 { IIC_Wait_Ack(); IIC_Send_Byte(COMMAND >> 8); //传输高8位 IIC_Wait_Ack(); IIC_Send_Byte(COMMAND & 0xFF); //传输低8位 IIC_Wait_Ack(); } void SHT3x_READ_TEMP_Humi(uint16_t *dat) //SHT3x读取数据 { IIC_Start(); IIC_Send_Byte(SHTx_Device_ADDR << 1 | Write_DATA); //写入地址和写命令 SHT3x_WriteCommand(READOUT_FOR_PERIODIC_MODE); //读取周期测量寄存器中的值 //下面是开始读取数据,其中的指针dat存放结果,前三个存放温度值,后三个是湿度值,在前三个温度值里面, //dat[0]是温度的高八位,dat[1]是低八位,dat[2]是CRC校验 IIC_Start(); IIC_Send_Byte(SHTx_Device_ADDR << 1 | Read_DATA); //写入地址和读命令 IIC_Wait_Ack(); //前五次读取都要发送ack信号,最后一次就不用发了。 dat[0] = IIC_Read_Byte(1); //温度的高八位 dat[1] = IIC_Read_Byte(1); //温度的低八位 dat[2] = IIC_Read_Byte(1); //温度的CRC位 dat[3] = IIC_Read_Byte(1); //湿度的高八位 dat[4] = IIC_Read_Byte(1); //湿度的低八位 dat[5] = IIC_Read_Byte(0); //湿度的CRC位 IIC_Stop(); } /* CRC校验函数(是确保通信过程中数据传输没问题的,没有缺少任何数据, 当我们接收到数据后,按照一定的方式计算一个crc校验码, 经过和提供的crc校验码进行比较,如果两个码一样,那么数据就是没问题的。) */ int CRC8_Compute(uint8_t *check_data, uint8_t num_of_data) { uint8_t bit; // bit mask uint8_t crc = 0xFF; // calculated checksum uint8_t byteCtr; // byte counter // calculates 8-Bit checksum with given polynomial for(byteCtr = 0; byteCtr < num_of_data; byteCtr++) { crc ^= (check_data[byteCtr]); //crc校验,最高位是1就^0x31 for(bit = 8; bit > 0; --bit) { if(crc & 0x80) crc = (crc << 1) ^ 0x31; else crc = (crc << 1); } } return crc; } int SHT3x_CRC8_Check(uint8_t *p,uint8_t num_of_data,uint8_t CrcData) { uint8_t crc; crc = CRC8_Compute(p, num_of_data);// calculates 8-Bit checksum if(crc != CrcData) { return 1; } return 0; } uint8_t SHT3x_Data_Process(void) //温湿度测量函数 { uint8_t temporary[3]; uint16_t data; uint8_t crc_result; SHT3x_READ_TEMP_Humi(data_process.sht30_data_buffer); //先处理温度的相关数据,位于数组的前三个 temporary[0]=data_process.sht30_data_buffer[0]; temporary[1]=data_process.sht30_data_buffer[1]; temporary[2]=data_process.sht30_data_buffer[2]; //crc校验 crc_result=SHT3x_CRC8_Check(temporary,2,temporary[2]); //crc校验要是不成功就返回1,同时不会更新温度值 if(crc_result==0) { //把2个8位数据拼接为一个16位的数据 data=((uint16_t)temporary[0] << 8) | temporary[1]; //温度转换,将16位温度数据转化为10进制的温度数据,这里保留了一位小数,data_process.SHT30_temperature这是一个全局变量 data_process.SHT30_temperature = ((175.0f * ((float)data) / 65535.0f - 45.0f) *1.0f); } else { return 1; } temporary[0]=data_process.sht30_data_buffer[3]; temporary[1]=data_process.sht30_data_buffer[4]; temporary[2]=data_process.sht30_data_buffer[5]; //crc校验 crc_result=SHT3x_CRC8_Check(temporary,2,temporary[2]); if(crc_result==0) { //参考上面温度的代码 data=((uint16_t)temporary[0] << 8) | temporary[1]; //湿度转换,将16位温度数据转化为10进制的温度数据,这里保留了一位小数,data_process.SHT30_temperature这是一个全局变量 data_process.SHT30_humidity = ((100.0f * (float)data / 65535.0f) *1.0f); return 0; } else { return 2; } } sht3x.h #ifndef __SHT3x_H #define __SHT3x_H #include "stm32f1xx_hal.h" #include "myiic.h" #include "usart.h" typedef enum{ SHTx_Device_ADDR = 0x44, //设备地址 Write_DATA = 0x00, //写数据/命令 Read_DATA = 0x01, //读数据/命令 SOFT_RESET_CMD = 0x30A2, //软件复位命令 /* 单次测量模式 */ CLOCK_HIGH_ENABLED_CMD = 0x2C06, CLOCK_MEDIUM_ENABLED_CMD = 0x2C0D, CLOCK_LOW_ENABLED_CMD = 0x2C10, CLOCK_HIGH_DISABLED_CMD = 0x2400, CLOCK_MEDIUM_DISABLED_CMD = 0x240B, CLOCK_LOW_DISABLED_CMD = 0x2416, /* 周期测量模式 */ PERI_HIGH_0_5_CMD = 0x2032, PERI_MEDIUM_0_5_CMD = 0x2024, PERI_LOW_0_5_CMD = 0x202F, PERI_HIGH_1_CMD = 0x2130, PERI_MEDIUM_1_CMD = 0x2126, PERI_LOW_1_CMD = 0x212D, //1s测量一次(1Hz) PERI_HIGH_2_CMD = 0x2236, PERI_MEDIUM_2_CMD = 0x2220, PERI_LOW_2_CMD = 0x222B, PERI_HIGH_4_CMD = 0x2334, PERI_MEDIUM_4_CMD = 0x2322, PERI_LOW_4_CMD = 0x2329, PERI_HIGH_10_CMD = 0x2737, PERI_MEDIUM_10_CMD = 0x2721, PERI_LOW_10_CMD = 0x272A, //1s测量10次(10Hz) HEATER_ENABLED_CMD = 0x306D, //加热器使能 HEATER_DISABLED_CMD = 0x3066, //加热器失能 READ_STATUS_CMD = 0xF32D, //读取状态寄存器 CLEAR_STATUS_CMD = 0x3041, //清除状态寄存器 READOUT_FOR_PERIODIC_MODE = 0xE000, // 周期测量模式读取数据命令 }SHT30_CMD; typedef struct { unsigned short int sht30_data_buffer[6]; float SHT30_temperature; //温度 float SHT30_humidity; //湿度 }_TW; extern _TW data_process; //定义温湿度结构体 void SHT3x_Init(void); //SHT30初始化 void SHT3x_READ_TEMP_Humi(uint16_t *dat); //写一个命令给SHT30,并读取数据 uint8_t SHT3x_Data_Process(void); //温湿度测量函数 // CRC校验函数 int CRC8_Compute(uint8_t *check_data, uint8_t num_of_data); int SHT3x_CRC8_Check(uint8_t *p,uint8_t num_of_data,uint8_t CrcData); 3,使用说明 调用SHT3x_Init初始化函数 周期调用SHT3x_Data_Process数据测量函数 所需数据在结构体data_process中 |
|
|
|
|
只有小组成员才能发言,加入小组>>
1599 浏览 0 评论
imx6ull 和 lan8742 工作起来不正常, ping 老是丢包
4738 浏览 0 评论
4229 浏览 9 评论
3822 浏览 16 评论
4398 浏览 1 评论
4212浏览 3评论
2381浏览 0评论
3394浏览 0评论
1159浏览 0评论
2844浏览 0评论
/9
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-12-2 11:05 , Processed in 0.832991 second(s), Total 76, Slave 56 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191

淘帖
1275