针对上篇文章对于程序可移植性不强的问题进行优化,基本思路是首先搭建好IIC底层驱动程序,该程序可用于任何IIC通讯设备,然后针对不同的IIC设备单独编写应用程序,本篇文章仍以SHT30为例。
一、IIC底层驱动之myiic.h
#ifndef __MYIIC_H
#define __MYIIC_H
#include "sys.h"
//IO方向设置
#define SDA_IN() {GPIOC->CRH&=0XFFFF0FFF;GPIOC->CRH|=8<<12;}
#define SDA_OUT() {GPIOC->CRH&=0XFFFF0FFF;GPIOC->CRH|=3<<12;}
//IO操作函数
#define IIC_SCL PCout(12) //SCL
#define IIC_SDA PCout(11) //SDA
#define READ_SDA PCin(11) //输入SDA
//IIC所有操作函数
void IIC_Init(void); //初始化IIC的IO口
void IIC_Start(void); //发送IIC开始信号
void IIC_Stop(void); //发送IIC停止信号
void IIC_Send_Byte(u8 txd); //IIC发送一个字节
u8 IIC_Read_Byte(unsigned char ack);//IIC读取一个字节
u8 IIC_Wait_Ack(void); //IIC等待ACK信号
void IIC_Ack(void); //IIC发送ACK信号
void IIC_NAck(void); //IIC不发送ACK信号
void IIC_Write_One_Byte(u8 daddr,u8 addr,u8 data);
u8 IIC_Read_One_Byte(u8 daddr,u8 addr);
#endif
二、IIC底层驱动之myiic.c
#include "myiic.h"
#include "delay.h"
//初始化IIC
void IIC_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
//RCC->APB2ENR|=1<<4;//先使能外设IO PORTC时钟
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
IIC_SCL=1;
IIC_SDA=1;
}
//产生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,接收应答成功
u8 IIC_Wait_Ack(void)
{
u8 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(u8 txd)
{
u8 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
u8 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;
}
三、IIC设备之SHT30.H
#ifndef SHT30_H
#define SHT30_H
#include "delay.h"
#include "sys.h"
#include "stdio.h"
#include "usart.h"
#include "string.h"
extern u8 humiture_buff1[20];
void SHT30_read_result(u8 addr);
#endif
四、IIC设备之SHT30.c
#include "SHT30.h"
#include "myiic.h"
#define write 0
#define read 1
float humiture[4];
u8 humiture_buff1[20];
/*******************************************************************
温湿度获取函数
函数原型: SHT30_read_result(u8 addr);
功能: 用来接收从器件采集并合成温湿度
********************************************************************/
void SHT30_read_result(u8 addr)
{
u16 tem,hum;
u16 buff[6];
float Temperature=0;
float Humidity=0;
IIC_Start();
IIC_Send_Byte(addr<<1 | write);//写7位I2C设备地址加0作为写取位,1为读取位
IIC_Wait_Ack();
IIC_Send_Byte(0x2C);
IIC_Wait_Ack();
IIC_Send_Byte(0x06);
IIC_Wait_Ack();
IIC_Stop();
delay_ms(50);
IIC_Start();
IIC_Send_Byte(addr<<1 | read);//写7位I2C设备地址加0作为写取位,1为读取位
if(IIC_Wait_Ack()==0)
{
buff[0]=IIC_Read_Byte(1);
buff[1]=IIC_Read_Byte(1);
buff[2]=IIC_Read_Byte(1);
buff[3]=IIC_Read_Byte(1);
buff[4]=IIC_Read_Byte(1);
buff[5]=IIC_Read_Byte(0);
IIC_NAck();
IIC_Stop();
}
tem = ((buff[0]<<8) | buff[1]);//温度拼接
hum = ((buff[3]<<8) | buff[4]);//湿度拼接
/*转换实际温度*/
Temperature= (175.0*(float)tem/65535.0-45.0) ;// T = -45 + 175 * tem / (2^16-1)
Humidity= (100.0*(float)hum/65535.0);// RH = hum*100 / (2^16-1)
if((Temperature>=-20)&&(Temperature<=125)&&(Humidity>=0)&&(Humidity<=100))//过滤错误数据
{
// humiture[0]=Temperature;
// humiture[2]=Humidity;
sprintf(humiture_buff1,"%6.2f*C %6.2f%%",Temperature,Humidity);//111.01*C 100.01%(保留2位小数)
}
printf("温湿度:%sn",humiture_buff1);
hum=0;
tem=0;
五、主函数之main.c
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "myiic.h"
#include "SHT30.h"
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2
delay_init(); //延时函数初始化
uart_init(9600); //串口初始化为9600
IIC_Init();
while(1)
{
SHT30_read_result(0x44);
}
}
六、串口显示实验结果
上一篇:STM32的I2C通讯配置(硬件实现)——学习笔记(6-2)
下一篇:STM32串口通讯协议浅析
推荐阅读最新更新时间:2024-11-20 06:13
设计资源 培训 开发板 精华推荐
- LT3973HDD 3.3V 降压转换器汽车应用的典型应用
- R1232D PWM 降压型 DC/DC 转换器的典型应用在固定输出电压类型下具有同步整流器
- MCP1501-18E/SN 1.800V 负参考电压的典型应用电路
- 采用 9V 碱性电池的 LTC3245HMSE 高效 3.3V 微控制器电源的典型应用电路
- AM30EW-4805SZ 5V 单路输出 DC/DC 转换器的典型应用
- TWR-56F8400: DSC MC56F84789电机和电源控制塔式系统模块
- 使用 MD1213 和 TC6320 100V 超声波脉冲器的高压脉冲器电路
- 40%矮轴机械键盘 Cherry Low to TTC
- NCV33072DR2G 单位增益缓冲器的典型应用 (AV = +1)
- 服务器风扇驱动
- 答题赢好礼|ADI技术直通车第1期
- 有奖报名|TI MSPM0 在【电力输送和工厂自动化与控制系统】、【家用电器和电机控制】中的典型应用
- TI|痛点解锁机:你的电源设计痛点,我们懂!解锁、评论赢好礼!
- 有奖直播|TI MSP430™民用超声波水表开发指南及其智能模拟组合模块在传感器检测中的应用
- TE 《新趋势报告: 如何有效应对当下测试测量领域的挑战》下载最新趋势报告
- 是德科技有奖问答活动之一,A4WP无线充电测试的示波器方案,答题闯关赢好礼!
- 英飞凌ADAS解决方案,确保您每一次安全出行 参与赢好礼!
- 995美元Spartan6开发板,花落谁家?
- TI带你一起玩转复杂汽车电子设计技能
- 挑战极限,你敢看吗?下载文档+观看视频,了解航空和政府应用解决方案