04 蓝桥杯单片机设计与开发_基础模块_PCF8591

2023-11-02 01:40

本文主要是介绍04 蓝桥杯单片机设计与开发_基础模块_PCF8591,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、前言

03 蓝桥杯单片机设计与开发_基础模块_DS1302-CSDN博客,承接上文,本文将继续介绍剩余蓝桥杯涉及模块(PCF8591、AT24C02、PWM、串口通信、NE555以及超声波测距),为大家做出详细编程指导。

二、PCF8591 A/D 转换模块

笔者将基于蓝桥杯官方给的赛点资源包(蓝桥杯单片机设计与开发_赛点资源数据包)进行编程,为大家讲解编程调用各语句的含义,帮助大家编写温度传感器的程序,也便于大家记忆。

1、导入底层驱动代码

首先,创建工程和导入.c文件笔者已在文章(蓝桥杯单片机设计与开发_标准模板)中向大家详细介绍了,这里就不再赘述。
读者可下载赛点资源包(蓝桥杯单片机设计与开发_赛点资源数据包),解压后可得到以下图片所示文件。
在这里插入图片描述
我们双击打开文件“3-底层驱动代码参考”文件,将得到以下 .c.h 文件。接下来将 iic.ciic.h 文件拷贝到工程所在文件夹中,并在编译器中将这两个文件导入,便可以开始编写程序了。
![[Pasted image 20231020210509.png]]

2、PCF8591 A/D转换函数封装

首先,在编写驱动函数之前,我们需要在底层驱动代码 iic.c 文件中编写 A/D转换函数,即 模拟量转化为数字量数字量转化为模拟量。我们可以打开赛点资源数据包中的文件“5-竞赛板芯片资料”。

在这里插入图片描述

打开“PCF8591”芯片手册。笔者将借助芯片手册中的资料编写温度读取函数并为大家讲解。
![[Pasted image 20231020210729.png]]

模拟量转化成数字量:编写AD转换函数,具体每条代码的含义都已经注释,在这里将不再赘述。

// 模拟量转化成数字量
unsigned char PCF8591_ADC(unsigned char addr)     
{unsigned char date;IIC_Start();              //开启总线IIC_SendByte(0x90);       //0x90: 1001 0000  向PCF8091写数据IIC_WaitAck();            //等待应答IIC_SendByte(addr);       //写数据IIC_WaitAck();            //等待应答IIC_Stop();               //关闭总线IIC_Start();              //开启总线IIC_SendByte(0x91);       //0x91: 1001 0001  向PCF8091读数据IIC_WaitAck();            //等待应答date = IIC_RecByte();     //接受数据IIC_SendAck(1);           //发送fei应答:已经读完数据IIC_Stop();               //关闭总线return date;
}

其中,在编写模数转换函数指令可通过查阅芯片资料手册,不需要死记硬背。

  • PCF8591芯片地址前四位默认为 10019
  • 后四位 A2\A1\A0 视具体的接线而定,最低位为 0 则表示向芯片写数据,为 1 则表示从芯片读数据。
    ![[Pasted image 20231020210919.png]]

数字量转化成模拟量:编写DA转换函数。

// 数字量转化成模拟量
void PCF8591_DAC(unsigned char date)     
{IIC_Start();              //开启总线IIC_SendByte(0x90);       //0x90: 1001 0000  向PCF8091写数据IIC_WaitAck();            //等待应答IIC_SendByte(0x40);       //告诉芯片要输出模拟量,即DAIIC_WaitAck();            //等待应答IIC_SendByte(date);       //IIC_WaitAck();            //等待应答IIC_Stop();               //关闭总线
}

同样可以查阅上述芯片资料手册,第六位为 1 时即表示输出模拟量,以及其他位的含义在芯片中都可以查找到,在这里还是想强调一下:初学者一定要学会看芯片手册,学会看手册对于你的代码水平一定会有提升
![[Pasted image 20231020211515.png]]

在编写完时间读写函数后务必要在 iic.h 文件中声明函数,才可在主函数中调用。

#ifndef _IIC_H
#define _IIC_H#include "STC15F2K60S2.h"
#include "intrins.h"sbit SDA = P2^1;  /* 数据线 */
sbit SCL = P2^0;  /* 时钟线 */unsigned char PCF8591_ADC(unsigned char addr);
void PCF8591_DAC(unsigned char date);#endif

3、主函数调用

在主函数中调用时间模块底层函数,首先需要在主函数开头包含驱动 iic.h 头文件。

#include "STC15F2K60S2.h"
#include "iic.h"

main主函数
主程序调用比较简单,下文中实现了 采用PCF8591 D/A模块输出电压,并通过按键修改输出电压值;并通过PCF8591 A/D模块Rb2电压和A/D脚电压,并通过数码管显示。由于考虑初学者基础较为薄弱,因此将完整的 main.cpp 代码贴出来,包含中断函数、矩阵键盘、数码管显示等,并且在关键处进行了注释,希望对大家有所帮助。

// 包含头文件
#include "STC15F2K60S2.h"
#include "iic.h"// 数据类型定义
#define u8 unsigned char
#define u16 unsigned int// 8位数码管状态
u8 dspbuf[8] = {10,10,10,10,10,10,10,10};  
u8 code tab[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0x89,0xc1,0xbf};//  0 ,  1 ,  2 ,  3 ,  4 ,  5 ,  6 ,  7 ,  8 ,  9 , 灭 , 0. , 1. , 2. , 3. , 4. , 5. , 6. , 7. , 8. , 9. ,  H ,  U ,  -  ; //  0 ,  1 ,  2 ,  3 ,  4 ,  5 ,  6 ,  7 ,  8 ,  9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 , 21 , 22 , 23  ;
u8 dspcom = 0,i;
bit key_flag = 0,iic_flag1 = 0,iic_flag2 = 0;// 定时器初始化
void Timer0Init(void)		//2毫秒@12.000MHz
{AUXR |= 0x80;		//定时器时钟1T模式TMOD &= 0xF0;		//设置定时器模式TL0 = 0x40;		//设置定时初值TH0 = 0xA2;		//设置定时初值TF0 = 0;		//清除TF0标志TR0 = 1;		//定时器0开始计时ET0 = 1;		//开定时中断EA= 1;			//开总中断
}// 573锁存器封装成函数
void door(u8 choose,u8 input)
{P2 = (P2 & 0x1f) | choose;P0 = input;P2 &= 0x1f;	
}// 关数码管
void clo_num()
{dspbuf[0] = 10;dspbuf[1] = 10;dspbuf[2] = 10;dspbuf[3] = 10;dspbuf[4] = 10;dspbuf[5] = 10;dspbuf[6] = 10;dspbuf[7] = 10;
}// 关灯、蜂鸣器、数码管
void all_init()	     
{door(0x80,0xff);door(0xa0,0xaf);clo_num();
}// 数码管显示函数
void display()
{			  door(0xe0,0xff);		//消隐door(0xc0,0x01<<dspcom);door(0xe0,tab[dspbuf[dspcom++]]);if(dspcom >= 8)     //or dspcom &= 0x07;dspcom = 0;
}// 矩阵键盘,接KBD
u8 keypress = 0,keyvalue = 0xff,keyread = 0;
u8 Read_key(void)		                             
{u8 key_m,cal;P3 = 0xf0;P42=1;P44=1;P36=P42;P37=P44;			   //变量替换key_m = (P3 & 0xf0);if(key_m != 0xf0) keypress++;elsekeypress = 0; if(keypress == 3){keypress = 0;keyread = 1;switch(key_m){case 0x70:cal = 0;break;                case 0xb0:cal = 1;break;    case 0xd0:cal = 2;break;    case 0xe0:cal = 3;break;}P3 = 0x0f;P42=0;P44=0;P36=P42;P37=P44;			   //变量替换key_m = (P3 & 0x0f);switch(key_m){case 0x0e:keyvalue = (4*cal+7);break;                case 0x0d:keyvalue = (4*cal+6);break;    case 0x0b:keyvalue = (4*cal+5);break;    case 0x07:keyvalue = (4*cal+4);break;}}P3 = 0x0f;P42=0;P44=0;P36=P42;P37=P44;			                //变量替换key_m = (P3&0x0f);if((keyread == 1) && (key_m == 0x0f)){keyread = 0;return keyvalue;	}return 0xff;  
}//````````````````````````````````主函数````````````````````````````````````
void main()		
{u8 key_re,iic_w = 0,vol = 0;int date_1,date_2;all_init();Timer0Init();// 数字量转为模拟量,此时可以在单片机D/A角上测到 200/255*5V 电压PCF8591_DAC(200);while(1){if(key_flag)			{key_flag = 0;key_re = Read_key();if(key_re != 0xff){switch(key_re){// 修改电压输出case 18:vol +=10;break;case 17:iic_w = 1;;break;case 16:iic_w = 0;clo_num();break;default:break;}// 设置修改的电压输出值PCF8591_DAC(vol);}}// 定时采集Rb2电压大小if((iic_flag1) && (iic_w)){iic_flag1 = 0;date_1 = PCF8591_ADC(0);       //测Rb2电压date_1 = 5*date_1/255.0*100;dspbuf[0] = date_1/100+11;dspbuf[1] = date_1%100/10;dspbuf[2] = date_1%10; }// 定时采集 A/D 引脚电压大小if((iic_flag2) && (iic_w)){iic_flag2 = 0;date_2 = PCF8591_ADC(3);      // 用A/D引脚测电压date_2 = 5*date_2/255.0*100;dspbuf[5] = date_2/100+11;dspbuf[6] = date_2%100/10;dspbuf[7] = date_2%10;}}
}// 定时器0中断服务函数
void timer0() interrupt 1	  
{static u8  t_20ms = 0,t_100ms = 0;   //MAX = 500 ms//不需要重载装载值display();		//数码管显示函数放里面t_20ms++;t_100ms++;if(t_20ms >= 10)	//每20ms扫描一次按键{t_20ms = 0;key_flag = 1;}if(t_100ms == 100)      {iic_flag1 = 1;}if(t_100ms == 200){t_100ms = 0;iic_flag2 = 1;}
}

至此,本次 PCF8591 A/D转换模块已介绍完毕。

这篇关于04 蓝桥杯单片机设计与开发_基础模块_PCF8591的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/327214

相关文章

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型的操作流程

《0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeekR1模型的操作流程》DeepSeekR1模型凭借其强大的自然语言处理能力,在未来具有广阔的应用前景,有望在多个领域发... 目录0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型,3步搞定一个应

Python利用自带模块实现屏幕像素高效操作

《Python利用自带模块实现屏幕像素高效操作》这篇文章主要为大家详细介绍了Python如何利用自带模块实现屏幕像素高效操作,文中的示例代码讲解详,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1、获取屏幕放缩比例2、获取屏幕指定坐标处像素颜色3、一个简单的使用案例4、总结1、获取屏幕放缩比例from

nginx-rtmp-module模块实现视频点播的示例代码

《nginx-rtmp-module模块实现视频点播的示例代码》本文主要介绍了nginx-rtmp-module模块实现视频点播,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习... 目录预置条件Nginx点播基本配置点播远程文件指定多个播放位置参考预置条件配置点播服务器 192.

基于Python开发PPTX压缩工具

《基于Python开发PPTX压缩工具》在日常办公中,PPT文件往往因为图片过大而导致文件体积过大,不便于传输和存储,所以本文将使用Python开发一个PPTX压缩工具,需要的可以了解下... 目录引言全部代码环境准备代码结构代码实现运行结果引言在日常办公中,PPT文件往往因为图片过大而导致文件体积过大,

使用DeepSeek API 结合VSCode提升开发效率

《使用DeepSeekAPI结合VSCode提升开发效率》:本文主要介绍DeepSeekAPI与VisualStudioCode(VSCode)结合使用,以提升软件开发效率,具有一定的参考价值... 目录引言准备工作安装必要的 VSCode 扩展配置 DeepSeek API1. 创建 API 请求文件2.

基于Python开发电脑定时关机工具

《基于Python开发电脑定时关机工具》这篇文章主要为大家详细介绍了如何基于Python开发一个电脑定时关机工具,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 简介2. 运行效果3. 相关源码1. 简介这个程序就像一个“忠实的管家”,帮你按时关掉电脑,而且全程不需要你多做

Java中的Opencv简介与开发环境部署方法

《Java中的Opencv简介与开发环境部署方法》OpenCV是一个开源的计算机视觉和图像处理库,提供了丰富的图像处理算法和工具,它支持多种图像处理和计算机视觉算法,可以用于物体识别与跟踪、图像分割与... 目录1.Opencv简介Opencv的应用2.Java使用OpenCV进行图像操作opencv安装j

Python中的可视化设计与UI界面实现

《Python中的可视化设计与UI界面实现》本文介绍了如何使用Python创建用户界面(UI),包括使用Tkinter、PyQt、Kivy等库进行基本窗口、动态图表和动画效果的实现,通过示例代码,展示... 目录从像素到界面:python带你玩转UI设计示例:使用Tkinter创建一个简单的窗口绘图魔法:用

多模块的springboot项目发布指定模块的脚本方式

《多模块的springboot项目发布指定模块的脚本方式》该文章主要介绍了如何在多模块的SpringBoot项目中发布指定模块的脚本,作者原先的脚本会清理并编译所有模块,导致发布时间过长,通过简化脚本... 目录多模块的springboot项目发布指定模块的脚本1、不计成本地全部发布2、指定模块发布总结多模