基于STC12C5A60S2系列1T 8051单片的IIC总线器件模数芯片PCF8591实现模数转换应用

基于STC12C5A60S2系列1T 8051单片的IIC总线器件模数芯片PCF8591实现模数转换应用

  • STC12C5A60S2系列1T 8051单片机管脚图
  • STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式及配置
  • STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式介绍
  • IIC总线器件模数芯片PCF8591介绍
    • 通过IIC总线器件模数芯片PCF8591把电压模拟量转化为电压数字量

STC12C5A60S2系列1T 8051单片机管脚图

在这里插入图片描述在这里插入图片描述

STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式及配置

在这里插入图片描述

STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式介绍

在这里插入图片描述在这里插入图片描述

IIC总线器件模数芯片PCF8591介绍

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

通过IIC总线器件模数芯片PCF8591把电压模拟量转化为电压数字量

在这里插入图片描述在这里插入图片描述

#include <stc12c5a60s2.h>
#include <intrins.h>
#define uchar unsigned char//自定义无符号字符型为uchar
#define uint unsigned int//自定义无符号整数型为uint 
#define NixieTubeSegmentCode P0//自定义数码管段码为单片机P0组引脚
#define NixieTubeBitCode P2//自定义数码管位码为单片机P2组引脚
//#define KeyPressDeshakeTime 10//自定义按键按下消抖时间为10ms
//#define KeyLongPressDelayTime 500//自定义按键长按延时时间为500ms
//#define KeyLongPressIntervalChangeTime 25//自定义按键长按间隔变化时间为25ms
//uchar AddKeyLockFlag;//声明增加按键锁定标志位变量
//uchar DecKeyLockFlag;//声明减少按键锁定标志位变量
//uchar KeyNumber = 0;//定义按键键值为0
//uchar AddKeyLongPressAddIntervalTime;//声明增加按键长按连增间隔时间变量
//uchar DecKeyLongPressDecIntervalTime;//声明减少按键长按连减间隔时间变量
//uchar NumberValue;//声明数字量变量
uchar Code NixieTubeBitCodeArray = [0xfe,0xfd,0xfb,0xf7];//定义共阴数码管位码数组变量
uchar NixieTubeDisplayDataArray[0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40,0x00];//定义共阴数码管显示0~F数据、符号“—”及熄灭数组变量
uchar NixieTubeCacheDataArray[];//定义数码管缓存数据数组变量
//uint AddKeyPressDelayTime;//声明增加按键按下延时时间变量
//uint DecKeyPressDelayTime;//声明减少按键按下延时时间变量
float OutPutVoltage;//声明输出电压变量
float AnalogFilterOutPutVoltage;//声明模拟滤波后输出电压变量
//uint Timer0TimeCount;//声明定时器0定时计数变量
//sbit AddKey = P3^0;//位定义增加按键为单片机P3.0引脚
//sbit DecKey = P3^1;//位定义减少按键为单片机P3.1引脚
sbit I2CSCL = P1^0;//位定义I2C时钟变量为P1.0端口
sbit I2CSDA = P1^1;//位定义I2C数据变量为P1.1端口void PCF8591Change(uchar Address,uchar Channel)//PCF8591转化函数
{uchar AnalogChangeResult;//声明模拟转换结果变量I2CStar();//I2C启动函数if(I2CWriteByte(Address << 1))//判断I2C写器件地址是否有应答 如果括号里面条件为真 执行{}里面代码跳出 表示I2C写器件地址没有应答 即没连接上I2C器件{I2CStop();//I2C停止函数return 0;//返回0}I2CWriteByte(Channel);//选I2C模拟通道I2CStar();//I2C启动函数I2CWriteByte((Address << 1)| 0x01);//I2C读操作I2CReadByte();//I2C读字节函数SendAck(0);//I2C发送应答AnalogChangeResult = I2CReadByte();//I2C读到的数据赋给模拟转换结果变量SendAck(1);//I2C不应答I2CStop();//I2C停止函数return AnalogChangeResult;//返回模拟转换结果变量包含的模拟数据}void I2CDelay()//I2C延时函数
{_nop_();_nop_();_nop_();_nop_();}void I2CStar()//I2C启动函数
{I2CSCL = 1;//空闲时 I2C时钟变量置高电平I2CSDA = 1;//空闲时 I2C数据变量置高电平I2CDelay();//I2C延时I2CSDA = 0;//I2C数据变量置低电平I2CDelay();//I2C延时I2CSCL = 0;//I2C时钟变量置低电平}bit I2CWriteByte(uchar Data)//I2C写字节函数
{uchar Temp;//声明临时变量bit Ack;//声明一位应答变量for(Temp = 0x80;Temp = !0;Temp >>= 1)//从某八位二进制数的最高位往最低位每次移出一位二进制数 取变化后的八位二进制数进行下一步从最高位往最低位每次右移出一位二进制数 直到写完某八位二进制数的每一位二进制数{if((Temp & Data) == 0)//判断临时变量包含的数据与上输入数模芯片PCF8591的八位二进制数得出八位二进制数最高位是否为0I2CSDA = 0;//I2C数据变量写0else//否则I2CSDA = 1;//I2C数据变量写1I2CDelay();//I2C延时I2CSCL = 1;//I2C时钟变量置高电平I2CDelay();//I2C延时I2CSCL = 0;//I2C时钟变量置低电平}Ack = I2CReceiveAck();//I2C接收应答函数接收应答赋给应答变量return (Ack);//返回应答}void SendAck(bit Ack)//I2C发送应答函数
{I2CSDA = Ack;//应答变量赋给I2C数据变量I2CDelay();//I2C延时I2CSCL = 1;//I2C时钟变量置高电平I2CDelay();//I2C延时I2CSCL = 0;//I2C时钟变量置低电平}bit ReceiveAck()//I2C接收应答函数
{bit Ack;//声明一位应答变量I2CSDA = 1;//I2C数据变量置高电平I2CDelay();//I2C延时I2CSCL = 1;//I2C时钟变量置高电平Ack = I2CSDA;//I2C数据变量I2CDelay();//I2C延时I2CSCL = 0;//I2C时钟变量置低电平return (Ack);//返回应答}uchar I2CReadByte()//I2C读字节函数
{uchar Data;//声明数据变量uchar Temp;//声明临时变量I2CSDA = 1;//I2C数据变量置高电平for(Temp = 0x80;Temp = !0;Temp >>= 1)//从某八位二进制数的最高位往最低位每次右移出一位二进制数 取变化后的八位二进制数进行下一步从最高位往最低位每次右移出一位二进制数 直到读完某八位二进制数的每一位二进制数{I2CDelay();//I2C延时I2CSCL = 1;//I2C时钟变量置高电平if(I2CSDA == 1)//判断I2C数据变量是否置高电平{Data |= Temp;//临时变量包含的数据或上某八位二进制数读出八位二进制数最高位为1}else//否则{Data &= ~Temp;//临时变量包含的数据与上某八位二进制数读出八位二进制数最高位为0}I2CDelay();//I2C延时I2CSCL = 0;//I2C时钟变量置低电平}return Data;//返回数据变量}void I2CStop()//I2C停止函数
{I2CSCL = 0;//I2C时钟变量置低电平I2CSDA = 0;//I2C数据变量置低电平I2CDelay();//I2C延时I2CSCL = 1;//I2C时钟变量置高电平I2CDelay();//I2C延时I2CSDA = 1;//I2C数据变量置高电平I2CDelay();//I2C延时}/****void KeyScan()//按键扫描函数 该函数放在定时器定时1ms的中断函数中扫描
{if(AddKey)//如果增加按键没按下或弹起{AddKeyLockFlag = 0;//增加按键锁定标志位清0AddKeyPressDelayTime = 0;//增加按键按下延时时间清0}   else if(!AddKeyLockFlag)//如果增加按键锁定标志位置1 即增加按键按下{AddKeyPressDelayTime++;//增加按键按下延时时间自加if(AddKeyPressDelayTime > KeyPressDeshakeTime)//如果增加按键按下延时时间大于按键按下消抖时间{AddKeyPressDelayTime = 0;//增加按键按下延时时间清0KeyNumber = 1;//按键键值置1 此处是单击增加 可赋给swicth()语句中的变量来对数值单击增加AddKeyLockFlag = 1;//增加按键锁定标志位置1}}else if(AddKeyPressDelayTime < KeyLongPressDelayTime)//如果增加按键按下延时时间小于按键长按延时时间{AddKeyPressDelayTime++;//增加按键按下延时时间自加}else//如果增加按键按下延时时间大于按键长按延时时间{AddKeyLongPressAddIntervalTime++;//增加按键长按连增间隔时间自加if(AddKeyLongPressAddIntervalTime > KeyLongPressIntervalChangeTime)//如果增加按键长按连增间隔时间大于按键长按间隔变化时间{AddKeyLongPressAddIntervalTime = 0;//增加按键长按连增间隔时间清0KeyNumber = 1;//按键键值置1 此处是连击增加 可赋给swicth()语句中的变量来对数值连击增加}}   if(DecKey)//如果减少按键没按下或弹起{DecKeyLockFlag = 0;//减少按键锁定标志位清0DecKeyPressDelayTime = 0;//减少按键按下延时时间清0}   else if(!DecKeyLockFlag)//如果减少按键锁定标志位置1 即减少按键按下{DecKeyPressDelayTime++;//减少按键按下延时时间自加if(DecKeyPressDelayTime > KeyPressDeshakeTime)//如果减少按键按下延时时间大于按键按下消抖时间{DecKeyPressDelayTime = 0;//减少按键按下延时时间清0KeyNumber = 2;//按键键值置2 此处是单击减少 可赋给swicth()语句中的变量来对数值单击减少DecKeyLockFlag = 1;//减少按键锁定标志位置1}}else if(DecKeyPressDelayTime < KeyLongPressDelayTime)//如果减少按键按下延时时间小于按键长按延时时间{DecKeyPressDelayTime++;//减少按键按下延时时间自加}else//如果减少按键按下延时时间大于按键长按延时时间{DecKeyLongPressDecIntervalTime++;//减少按键长按连减间隔时间自加if(DecKeyLongPressDecIntervalTime > KeyLongPressIntervalChangeTime)//如果减少按键长按连减间隔时间大于按键长按间隔变化时间{DecKeyLongPressDecIntervalTime = 0;//减少按键长按连减间隔时间清0KeyNumber = 2;//按键键值置2 此处是连击减少 可赋给swicth()语句中的变量来对数值连击减少}}}****//****void NumberValueSet()//数字量数值设置函数
{switch(KeyNumber)//按键类型筛选位{case 1 ://增加按键单击、长按触发位NumberValue++;//数字量数值自加if(NumberValue > 255)//如果数字量数值大于255 为啥数字量数值变量NumberValue取255来比较?由于数字量数值变量NumberValue要计入PCF8591转换器 而PCF8591转换器是十位寄存器 最大只能计入255 因此数字量数值变量NumberValue取255来比较{NumberValue = 255;//数字量数值等于255}KeyNumber = 0;//按键键值清0break;//跳出case 2 ://减少按键单击、长按触发位NumberValue--;//数字量数值自减if(NumberValue < 0)//如果数字量数值小于0{NumberValue = 0;//数字量数值清0}KeyNumber = 0;//按键键值清0break;//跳出default:break;//跳出}}****/void NixieTubeDisplayDataSplit()//数码管显示数据分解函数
{uchar NixieTubeQianWei,NixieTubeBaiWei,NixieTubeShiWei,NixieTubeGewei;//声明数码管千位、百位、十位、个位变量NixieTubeQianWei = AnalogFilterOutPutVoltage / 1000 ;//数码管千位分解NixieTubeBaiWei = AnalogFilterOutPutVoltage / 100 % 10;//数码管百位分解NixieTubeShiWei = AnalogFilterOutPutVoltage / 10 % 10 ;//数码管十位分解NixieTubeGeWei = AnalogFilterOutPutVoltage % 10 ;//数码管个位分解NixieTubeCacheDataArray[0] = NixieTubeQianWei;//数码管千位显示数据NixieTubeCacheDataArray[1] = NixieTubeBaiWei +15;//数码管百位带小数点显示数据NixieTubeCacheDataArray[2] = NixieTubeShiWei;//数码管十位显示数据NixieTubeCacheDataArray[3] = NixieTubeGeWei;//数码管个位显示数据}void NixieTubeDisplayData()//数码管显示数据函数  
{  static uchar i = 0;//定义静态数码管位变化变量switch(i)//数码管位变化筛选{case 0 ://数码管千位显示NixieTubeSegmentCode = 0x00;//数码管段码消影NixieTubeSegmentCode = NixieTubeDisplayDataArray[NixieTubeCacheDataArray[0]];//数码管千位的段码显示NixieTubeBitCode = NixieTubeBitCodeArray[0];//数码管千位码显示i++;//数码管位变化自加1break;//跳出case 1 ://数码管百位显示NixieTubeSegmentCode = 0x00;//数码管段码消影NixieTubeSegmentCode = NixieTubeDisplayDataArray[NixieTubeCacheDataArray[1]];//数码管百位的段码显示NixieTubeBitCode = NixieTubeBitCodeArray[1];//数码管百位码显示i++;//数码管位变化自加1break;//跳出 case 2 ://数码管十位显示NixieTubeSegmentCode = 0x00;//数码管段码消影NixieTubeSegmentCode = NixieTubeDisplayDataArray[NixieTubeCacheDataArray[2]];//数码管十位的段码显示NixieTubeBitCode = NixieTubeBitCodeArray[2];//数码管十位码显示i++;//数码管位变化自加1break;//跳出case 3 ://数码管个位显示NixieTubeSegmentCode = 0x00;//数码管段码消影NixieTubeSegmentCode = NixieTubeDisplayDataArray[NixieTubeCacheDataArray[3]];//数码管个位的段码显示NixieTubeBitCode = NixieTubeBitCodeArray[3];//数码管个位码显示i = 0;//数码管位变化清0break;//跳出default:break;//跳出}} void Timer0Init()//定时器0的16位定时模式1用12分频定时1ms初始化函数 晶振为12MHz
{AUXR &= 0x7f;//设定定时器/计数器模式为12TTMOD &= 0xf0;//设定定时器/计数器工作模式清0TMOD |= 0x01;//设定定时器/计数器为定时器 工作模式为16位定时器0模式1TH0 = 0xfc;//设定定时器0高8位初值 TL0 = 0x18;//设定定时器0低8位初值TF0 = 0;//定时器0溢出中断标志位清0ET0 = 1;//打开定时器中断开关EA = 1;//打开定时器中断总开关TR0 = 1//打开定时器0开关} void Timer0() interrupt 1//定时器0的16位定时模式1用12分频定时1ms中断函数 晶振为12MHz
{TR0 = 0;//关定时器0开关/***Timer0TimeCount++;//定时器0定时计数自加if(Timer0TimeCount >= 10)//10ms时间到{Timer0TimeCount = 0;//定时器0定时计数清0PCF8591Change(NumberValue);//PCF8591转化函数 }***///KeyScan();//按键扫描函数NixieTubeDisplayData();//数码管显示数据函数TH0 = 0xfc;//设定定时器0高8位初值TL0 = 0x18;//设定定时器0低8位初值TR0 = 1;//开定时器0开关} void main()//主函数
{uchar AnalogDataResult;//声明模拟数字结果变量uchar AnalogSamplingCount;//声明模拟采样计数变量uint AnalogFilterVoltage;//声明模拟滤波电压变量Timer0Init();//定时器0的16位定时模式1用12分频定时1ms初始化函数 晶振为12MHz//NumberValueSet();//数字量数值设置函数while(1)//主循环{AnalogDataResult = PCF8591Change(0x48,0);//PCF8591转化函数转化的模拟数据赋给模拟数据结果变量  OutPutVoltage = AnalogDataResult*1.0*250/255;//输出电压计算公式 250是基准电压2.5V转化成250mv 255是模数芯片PCF8591内部八位模拟转换寄存器能够储存的最大数值AnalogFilterVoltage = AnalogFilterVoltage + OutPutVoltage;//模拟滤波电压变量AnalogSamplingCount++;//模拟采样计数变量自加1if(AnalogSamplingCount >= 8)//模拟采样计数变量计8次{AnalogFilterOutPutVoltage = AnalogFilterVoltage >> 3;//模拟滤波电压变量右移三位 表示模拟滤波电压变量除以8取平均滤波后的输出电压AnalogSamplingCount = 0;//模拟采样计数变量清0AnalogFilterVoltage = 0;//模拟滤波电压变量清0  }NixieTubeDisplayDataSplit()//数码管显示数据分解函数}}  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/188882.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Leetcode -2

Leetcode Leetcode -234.回文链表Leetcode -160.相交链表 Leetcode -234.回文链表 题目&#xff1a;给你一个单链表的头节点 head &#xff0c;请你判断该链表是否为回文链表。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 示例 1&#xff1a; 输…

最新AI创作系统ChatGPT系统运营源码+支持GPT-4多模态模型

一、AI创作系统 SparkAi创作系统是基于OpenAI很火的ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如…

2023年03月 Scratch(一级)真题解析#中国电子学会#全国青少年软件编程等级考试

Scratch等级考试(1~4级)全部真题・点这里 一、单选题(共25题,每题2分,共50分) 第1题 下列说法不正确的是?( ) A:可以从声音库中随机导入声音 B:可以录制自己的声音上传 C:可以修改声音的大小 D:不能修改声音的速度 答案:D 针对声音可以进行导入,上传,修改…

vue监听对象属性值变化

一、官方文档 二、实现方法 方法一、直接根据watch来监听 export default {data() {return {object: {username: ,password: }}},watch: {object.username(newVal, oldVal) {console.log(newVal, oldVal)}} }方法二&#xff1a;利用watch和computed来实现监听 利用computed定…

springcloud新闻发布系统源码

开发技术&#xff1a; jdk1.8&#xff0c;mysql5.7&#xff0c;nodejs&#xff0c;idea&#xff0c;vscode springcloud springboot mybatis vue elementui 功能介绍&#xff1a; 用户端&#xff1a; 登录注册 首页显示搜索新闻&#xff0c;新闻分类&#xff0c;新闻列表…

我的 2023 秋招总结,拿到了大厂offer

2023秋招小结 前言 & 介绍 作为2024年毕业的学生&#xff0c;在2023年也就是今年秋招。 现在秋招快结束了&#xff0c;人生可能没有几次秋招的机会&#xff08;应该就一次&#xff0c;最多两次吧哈哈&#xff09;&#xff0c;也有一点感悟&#xff0c;所以小小总结一下。…

音频类型转换工具-可执行文件exe/dmg制作

朋友车载音乐需要MP3格式&#xff0c;想要个批量转换工具 准备工作 brew install ffmpeg --HEAD或者官网下载安装ffmpeg并配置环境conda install ffmpeg 或者pip install ffmpeg-python 音频类型转换程序.py文件 exe文件在windows下打包&#xff0c;dmg在macos下打包&#…

quickapp_快应用_tabBar

tabBar 配置项中配置tabBar(版本兼容)使用tabs组件配置tabBar语法示例问题-切换tab没有反应问题-数据渲染问题解决优化 问题-tab的动态配置 第三方组件tabbar 一般首页都会显示几个tab用于进行页面切换&#xff0c;以下是几种tab配置方式。 配置项中配置tabBar(版本兼容) 在m…

C语言一个奇奇怪怪的小细节(定制初始化中的一个坑)

在今天写C代码的过程中&#xff0c;发现了一个奇怪的现象&#xff1a; 假设我们有如下数据结构&#xff1a; struct AddressMapping {u64 lba;union{u64 addr;u64 addrPage;struct ScatterIter sgiter;};u64 size; }__attribute__ ((__packed__));struct ScatterIter{struct Sc…

一文看分布式锁

为什么会存在分布式锁&#xff1f; 经典场景-扣库存&#xff0c;多人去同时购买一件商品&#xff0c;首先会查询判断是否有剩余&#xff0c;如果有进行购买并扣减库存&#xff0c;没有提示库存不足。假如现在仅存有一件商品&#xff0c;3人同时购买&#xff0c;三个线程同时执…

最新自动定位版本付费进群系统源码

更新内容&#xff1a; 1.在网站首页增加了付款轮播功能。 2.新增了城市定位功能&#xff0c;方便用户查找所在城市的相关信息。 3.对域名库及支付设置进行了更新和优化。 4.增加了一种图模板设置模式&#xff0c;简化了后台模板设置流程。 5.此外还进行了前后台的其他优化…

ClickHouse的分片和副本

1.副本 副本的目的主要是保障数据的高可用性&#xff0c;即使一台ClickHouse节点宕机&#xff0c;那么也可以从其他服务器获得相同的数据。 Data Replication | ClickHouse Docs 1.1 副本写入流程 1.2 配置步骤 &#xff08;1&#xff09;启动zookeeper集群 &#xff08;2&…