前言

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模块相关推荐

  1. 参考任哲的《嵌入式实时操作系统μC_OS-II原理及应用》,对UCOS的任务调度做了下整理。

    参考任哲的< 嵌入式 实时操作系统μC_OS-II原理及应用>,对 UCOS 的任务调度做了下整理. UCOS有两种调度器,一种是任务级的调度器,一种是中断级的调度器.任务级的调度器由OS ...

  2. 从零开始构建嵌入式实时操作系统2——重构

    1.前言 本人是一个普通的中年程序员,并不是圈内的大牛,写嵌入式操作系统这一系列的文章并不是要显示自己的技术,而是出于对嵌入式的热爱.非常幸运,本人毕业后的十几年一直从事嵌入式行业,遇到过各种坑,也收 ...

  3. 嵌入式实时操作系统1——初识嵌入式实时操作系统

    嵌入式实时操作系统是什么 嵌入式实时操作系统是一个特殊的程序,是一个支持多任务的运行环境.嵌入式实时操作系统最大的特点就是"实时性",如果有一个任务需要执行,实时操作系统会立即执行 ...

  4. 嵌入式实时操作系统ucosii原理及应用(任哲)-- --阅读笔记2

    本文是<嵌入式实时操作系统ucosii原理及应用(任哲)>一书第三章的阅读笔记,知识点多为摘录,若希望深入了解,请购买该书认真研读.由于一些知识比较零散,记起来不大方便,又习惯画图辅助记忆 ...

  5. 嵌入式实时操作系统ucosii原理及应用(任哲)

    本文是<嵌入式实时操作系统ucosii原理及应用(任哲)>一书第三章的阅读笔记,知识点多为摘录,若希望深入了解,请购买该书认真研读.由于一些知识比较零散,记起来不大方便,又习惯画图辅助记忆 ...

  6. 任哲《嵌入式实时操作系统uC/OS-II》 预备工具

    进入工作后,白天负责公司项目开发,晚上蹭加班绩效在公司学点别的东西.虽说待在嵌入式部门,但基本上负责的项目都是微控制器类方面的开发,所以要加强学习真正的嵌入式方面的学习.第一个坑uC/OS-II.我学 ...

  7. 嵌入式实时操作系统-VxWorks(基础)

    1.实时系统定义:是指那些产生系统输出的时间对于系统是至关重要的系统. 实时系统可根据时限对其性能(或效益)影响程度的不同,分为软实时系统SRT和硬实时系统HRT. 软时限是指时限的错过不会损害系统的 ...

  8. 嵌入式系统开发16——嵌入式实时操作系统uC/OS的简介及简单应用

    本文主要介绍嵌入式实时操作系统(RTOS),并且以uc/OS为例,将其移植到stm32F103C8T6上,构建3个任务:其中两个task分别以1s和3s周期对LED灯进行点亮-熄灭的控制:另外一个ta ...

  9. 嵌入式实时操作系统ucos-ii_「正点原子NANO STM32开发板资料连载」第三十六章 UCOSII 实验 1任务调度...

    1)实验平台:alientek NANO STM32F411 V1开发板2)摘自<正点原子STM32F4 开发指南(HAL 库版>关注官方微信号公众号,获取更多资料:正点原子 第三十六章 ...

  10. 嵌入式实时操作系统ucos-ii_「正点原子NANO STM32开发板资料连载」第三十八章 UCOSII 实验 3...

    1)实验平台:alientek NANO STM32F411 V1开发板2)摘自<正点原子STM32F4 开发指南(HAL 库版>关注官方微信号公众号,获取更多资料:正点原子 第三十八章 ...

最新文章

  1. SpringBoot开发案例之整合Dubbo提供者(二)
  2. python并发入门(part5 event对象)
  3. WCF完美搭建android平台服务之一
  4. windows下nodejs环境配置
  5. DTS-SHOP微信小程序多店铺商城平台java源码
  6. JVM系列五:垃圾回收器
  7. php ddos 防御,PHP DDos的几个防御方法详解
  8. 《遥感原理与应用》孙家抦版知识点总结(含简答题)——第四章
  9. 【3dmax千千问】初学3dmax插件神器第15课|打开疯狂模渲大师已归档效果图的模型场景,弹窗提示“无法创建备份文件”报错,室内设计师应该怎么办?
  10. kvm虚拟机管理工具列表
  11. python中的nmap模块(编写扫描器)
  12. Chinese-Whisper聚类算法
  13. SpringSecurity(二): @Secured、@PreAuthorize、@PostAuthorize、@PostFilter、@PreFilter注解说明
  14. BigDecimal的ROUND_DOWN()中的坑
  15. Gitea 的简单介绍
  16. Java 快乐练习口算
  17. 编辑引导扇区修复分区引导解决磁盘分区打不开
  18. 计算机如何自我介绍教程,2020计算机专业自我介绍4篇
  19. Unity3D RPG实现 2 —— 背包系统
  20. 3D格式转换工具HOOPS Exchange最全技术指南(一):4大功能特征与典型使用场景

热门文章

  1. 大数据正在遭遇成长的烦恼
  2. Java Quartz 刷新微信access_token
  3. 小病毒(恶作剧)与小宏病毒的学习
  4. 什么是区块链之简单直白解释
  5. core java detail
  6. 富人和穷人的十三大经典差异!!!
  7. 2020届拼多多web前端暑期实习生笔试
  8. PPT基础(六)组合与取消组合
  9. 硅谷不再:创业者和投资人都在离开
  10. 老中医推荐11个治疗咳嗽小偏方