嵌入式实时操作系统篇--I2C总线下PCF8574模块
前言
1.利用i2c协议驱动系统中的PCF8574模块进而控制蜂鸣器
一、i2c协议的简单描述
I2C设备连接I2C总线
SDA为数据线,SCL为时钟线,I2C由这两条线组成,其上连接由主机控制器和从设备。
起始位和停止位的条件
当SCL时钟线为高电平,SDA数据线由高变低时,为起始信号。SCL时钟线为高电平,SDA数据线由低变高时,为停止信号。
位传输
应答
二、硬件电路接口
1.I2C两条线的接口
2.PCF8574T原理图
3.蜂鸣器原理图
三、I2C协议的代码实现
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "delay.h"//IIC_SDA:PH5
//IIC_SCL:PH4void iic_init(){GPIO_InitTypeDef GPIO_InitStruct; //定义gpio初始化结构体 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOH, ENABLE); //查找手册能知道GPIOH连接在AHB1时钟线上,所以用这个函数对GPIOH使能GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; //端口模式为输出模式GPIO_InitStruct.GPIO_OType = GPIO_OType_OD; //端口输出类型为开漏模式GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5; //选择PH4 和 PH5 端口GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; //若外部有上拉,则可配置为无上下拉GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz; //标准速度仅100KGPIO_Init(GPIOH, &GPIO_InitStruct); ////3. 初始状态:空闲状态GPIO_SetBits(GPIOH,GPIO_Pin_5); //拉高SDA GPIO_SetBits(GPIOH,GPIO_Pin_4); //拉高SCLdelay_us(5); //这里采用软件延时
}
//起始条件:在SCL高电平期间,SDA从高到低跳变
void iic_start(){GPIO_SetBits(GPIOH,GPIO_Pin_5); //拉高SDA 此函数为设置高电平函数 第一个参数为具体GPIO 第二个是哪个端口设置为高电平GPIO_SetBits(GPIOH,GPIO_Pin_4); //拉高SCLdelay_us(5); ///这里采用软件延时GPIO_ResetBits(GPIOH,GPIO_Pin_5); //SDA从高到低跳变 此函数为设置低电平函数,参数和上述一样GPIO_ResetBits(GPIOH,GPIO_Pin_4); //每次操作完拉低SCL,继续占用总线delay_us(5);
}//停止条件:在SCL高电平期间,SDA从低到高跳变
void iic_stop(){GPIO_ResetBits(GPIOH,GPIO_Pin_5); //SDA为低GPIO_SetBits(GPIOH,GPIO_Pin_4); //SCL为高delay_us(5); GPIO_SetBits(GPIOH,GPIO_Pin_5); //SDA由低到高跳变delay_us(5);
}
//数据发送:低电平发数据,以字节为单位,先传高位
void iic_sendByte(u8 dat)
{u8 i = 0;for(i=0;i<8;i++){GPIO_ResetBits(GPIOH,GPIO_Pin_4); //拉低时钟,低电平发数据delay_us(5);if(dat & 0x80)GPIO_SetBits(GPIOH,GPIO_Pin_5); //发数据位1elseGPIO_ResetBits(GPIOH,GPIO_Pin_5); //发数据位0delay_us(5);GPIO_SetBits(GPIOH,GPIO_Pin_4); //拉高SCL,从机读取数据delay_us(5);dat <<= 1; //移掉高位,准备发次高位}GPIO_ResetBits(GPIOH,GPIO_Pin_4); //每次操作完拉低SCL,继续占用总线delay_us(5);
}//接收数据:在SCL高电平期间读取数据
u8 iic_recvByte()
{u8 i = 0;u8 temp = 0; //用于保存接收的数据for(i=0;i<8;i++){GPIO_ResetBits(GPIOH,GPIO_Pin_4); //主机拉低SCL,让从机发数据过来GPIO_SetBits(GPIOH,GPIO_Pin_5); //主机读数据前,先切断输出通道,切换为输入模式delay_us(5); GPIO_SetBits(GPIOH,GPIO_Pin_4); //拉高SCL,准备接收数据delay_us(5); if(GPIO_ReadInputDataBit(GPIOH, GPIO_Pin_5) == Bit_SET)temp |= 1<<(7-i); //接收数据位delay_us(5); }GPIO_ResetBits(GPIOH,GPIO_Pin_4); //每次操作完拉低SCL,继续占用总线delay_us(5); return temp;
}//主机向从机发送应答信号
void iic_ackToSlave()
{GPIO_ResetBits(GPIOH,GPIO_Pin_4); //拉低SCL,发应答信号delay_us(5); GPIO_ResetBits(GPIOH,GPIO_Pin_5); //拉低SDA,发应答delay_us(5); GPIO_SetBits(GPIOH,GPIO_Pin_4); //拉高SCL,使从机接收应答delay_us(5);GPIO_ResetBits(GPIOH,GPIO_Pin_4); //每次操作完拉低SCL,继续占用总线delay_us(5);
}//主机向从机发送非应答信号
void iic_noAckToSlave()
{GPIO_ResetBits(GPIOH,GPIO_Pin_4); //拉低SCL,发应答信号delay_us(5); GPIO_SetBits(GPIOH,GPIO_Pin_5); //拉高SDA,发非应答delay_us(5); GPIO_SetBits(GPIOH,GPIO_Pin_4); //拉高SCL,使从机接收应答delay_us(5);GPIO_ResetBits(GPIOH,GPIO_Pin_4); //每次操作完拉低SCL,继续占用总线delay_us(5);
}//从机向主机发应答,主机读取SDA,判断应答状态
u8 iic_checkAck()
{u8 ack = 0;GPIO_ResetBits(GPIOH,GPIO_Pin_4); //拉低SCL,使从机发应答信号GPIO_SetBits(GPIOH,GPIO_Pin_5); //主机读数据前,先切断输出通道,切换为输入模式delay_us(5);GPIO_SetBits(GPIOH,GPIO_Pin_4); //拉高SCL,准备接收应答delay_us(5);if(GPIO_ReadInputDataBit(GPIOH, GPIO_Pin_5) == Bit_SET) //从机向主机发非应答信号ack = 1;else if(GPIO_ReadInputDataBit(GPIOH, GPIO_Pin_5) == Bit_RESET) //从机向主机发应答信号ack = 0;delay_us(5);GPIO_ResetBits(GPIOH,GPIO_Pin_4); //每次操作完拉低SCL,继续占用总线delay_us(5);return ack;
}
四、PCF8574代码实现
#include "iic.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "pcf8574.h"void pcf8574_init()
{iic_init();
}
void pcf8574_writePort(u8 dat,u8 *err)
{u8 ack =0;iic_start();//主机启动总线iic_sendByte(PCF8574_ADD<<1); //发写数据地址 (rw=0) 查手册能知道从设备PCF8574的地址是0x20 //#define PCF8574_ADD 0x20ack = iic_checkAck();//从机向主机发应答,主机读取SDA,判断应答状态if(ack!=0) //寻址出错{ iic_stop(); //停止总线*err=1; //寻址出错,保存错误值return; //结束程序}iic_sendByte(dat); //发数据ack = iic_checkAck(); //if(ack !=0){ //从机不接受数据,写数据出错iic_stop(); *err = 2; return; }iic_stop(); //正常停止总线*err = 0;return;
}
//主机读取pcf8574端口状态
u8 pcf8574_readPort(u8 *err){u8 ack =0;u8 temp = 0;iic_start(); //主机启动总线iic_sendByte(PCF8574_ADD<<1); //发写数据的地址ack = iic_checkAck(); //从机应答if(ack != 0) //寻址出错{iic_stop(); //停止总线*err = 1; //寻址出错,保存错误值return; //结束程序}temp = temp = iic_recvByte(); //读取数据iic_noAckToSlave(); //主机回应不应答信号,不继续读取数据iic_stop(); //停止总线*err = 0; //无错误return temp; //返回读取的结果
}
五、蜂鸣器代码实现
由PCF8574T原理图可知道蜂鸣器接口连在P0口
#include "pcf8574.h"
#include "stm32f4xx.h"
#include <stdio.h>//初始化蜂鸣器,上电时不响
//蜂鸣器接口:接PCF8574的P0,低电平响
void beep_init()
{u8 temp = 0;u8 err = 0;pcf8574_init();temp = pcf8674_readPort(&err);if(err == 0){temp |= 0x01; //I/O端口从p0-p7 p0置1 蜂鸣器不响 所以进行或运算pcf8574_writePort(temp,&err); //得到的temp 写入pcf8574模块来驱动蜂鸣器if(err == 0)printf("beep init ok!\r\n");}elseprintf("beep init error!\r\n");
}//蜂鸣器发声
void beep_on()
{u8 err = 0;u8 temp = 0;temp = pcf8674_readPort(&err); if(err == 0){temp &= 0xfe; //p0置0pcf8574_writePort(temp,&err); //写入数据if(err != 0)printf("pcf8574 write error!\r\n");}else printf("pcf8574 status read error!\r\n");
}//蜂鸣器停止发声
void beep_off()
{u8 err = 0;u8 temp = 0;temp = pcf8674_readPort(&err);if(err == 0){temp |= 0x01;pcf8574_writePort(temp,&err);if(err != 0)printf("pcf8574 write error!\r\n");}else printf("pcf8574 status read error!\r\n");
}
总结
本章是小白的第一篇博客,主要表述了I2C总线是怎么驱动PCF8574模块下的蜂鸣器和简单的代码实现。有表述错误的地方请见谅!
嵌入式实时操作系统篇--I2C总线下PCF8574模块相关推荐
- 参考任哲的《嵌入式实时操作系统μC_OS-II原理及应用》,对UCOS的任务调度做了下整理。
参考任哲的< 嵌入式 实时操作系统μC_OS-II原理及应用>,对 UCOS 的任务调度做了下整理. UCOS有两种调度器,一种是任务级的调度器,一种是中断级的调度器.任务级的调度器由OS ...
- 从零开始构建嵌入式实时操作系统2——重构
1.前言 本人是一个普通的中年程序员,并不是圈内的大牛,写嵌入式操作系统这一系列的文章并不是要显示自己的技术,而是出于对嵌入式的热爱.非常幸运,本人毕业后的十几年一直从事嵌入式行业,遇到过各种坑,也收 ...
- 嵌入式实时操作系统1——初识嵌入式实时操作系统
嵌入式实时操作系统是什么 嵌入式实时操作系统是一个特殊的程序,是一个支持多任务的运行环境.嵌入式实时操作系统最大的特点就是"实时性",如果有一个任务需要执行,实时操作系统会立即执行 ...
- 嵌入式实时操作系统ucosii原理及应用(任哲)-- --阅读笔记2
本文是<嵌入式实时操作系统ucosii原理及应用(任哲)>一书第三章的阅读笔记,知识点多为摘录,若希望深入了解,请购买该书认真研读.由于一些知识比较零散,记起来不大方便,又习惯画图辅助记忆 ...
- 嵌入式实时操作系统ucosii原理及应用(任哲)
本文是<嵌入式实时操作系统ucosii原理及应用(任哲)>一书第三章的阅读笔记,知识点多为摘录,若希望深入了解,请购买该书认真研读.由于一些知识比较零散,记起来不大方便,又习惯画图辅助记忆 ...
- 任哲《嵌入式实时操作系统uC/OS-II》 预备工具
进入工作后,白天负责公司项目开发,晚上蹭加班绩效在公司学点别的东西.虽说待在嵌入式部门,但基本上负责的项目都是微控制器类方面的开发,所以要加强学习真正的嵌入式方面的学习.第一个坑uC/OS-II.我学 ...
- 嵌入式实时操作系统-VxWorks(基础)
1.实时系统定义:是指那些产生系统输出的时间对于系统是至关重要的系统. 实时系统可根据时限对其性能(或效益)影响程度的不同,分为软实时系统SRT和硬实时系统HRT. 软时限是指时限的错过不会损害系统的 ...
- 嵌入式系统开发16——嵌入式实时操作系统uC/OS的简介及简单应用
本文主要介绍嵌入式实时操作系统(RTOS),并且以uc/OS为例,将其移植到stm32F103C8T6上,构建3个任务:其中两个task分别以1s和3s周期对LED灯进行点亮-熄灭的控制:另外一个ta ...
- 嵌入式实时操作系统ucos-ii_「正点原子NANO STM32开发板资料连载」第三十六章 UCOSII 实验 1任务调度...
1)实验平台:alientek NANO STM32F411 V1开发板2)摘自<正点原子STM32F4 开发指南(HAL 库版>关注官方微信号公众号,获取更多资料:正点原子 第三十六章 ...
- 嵌入式实时操作系统ucos-ii_「正点原子NANO STM32开发板资料连载」第三十八章 UCOSII 实验 3...
1)实验平台:alientek NANO STM32F411 V1开发板2)摘自<正点原子STM32F4 开发指南(HAL 库版>关注官方微信号公众号,获取更多资料:正点原子 第三十八章 ...
最新文章
- SpringBoot开发案例之整合Dubbo提供者(二)
- python并发入门(part5 event对象)
- WCF完美搭建android平台服务之一
- windows下nodejs环境配置
- DTS-SHOP微信小程序多店铺商城平台java源码
- JVM系列五:垃圾回收器
- php ddos 防御,PHP DDos的几个防御方法详解
- 《遥感原理与应用》孙家抦版知识点总结(含简答题)——第四章
- 【3dmax千千问】初学3dmax插件神器第15课|打开疯狂模渲大师已归档效果图的模型场景,弹窗提示“无法创建备份文件”报错,室内设计师应该怎么办?
- kvm虚拟机管理工具列表
- python中的nmap模块(编写扫描器)
- Chinese-Whisper聚类算法
- SpringSecurity(二): @Secured、@PreAuthorize、@PostAuthorize、@PostFilter、@PreFilter注解说明
- BigDecimal的ROUND_DOWN()中的坑
- Gitea 的简单介绍
- Java 快乐练习口算
- 编辑引导扇区修复分区引导解决磁盘分区打不开
- 计算机如何自我介绍教程,2020计算机专业自我介绍4篇
- Unity3D RPG实现 2 —— 背包系统
- 3D格式转换工具HOOPS Exchange最全技术指南(一):4大功能特征与典型使用场景