LQB,手打,PCF8591,ADDA转换,AD1是光敏电阻,AD3是电位器,DA输出

news2024/11/20 3:34:51

在这里插入图片描述
在上述at24c02de 基础上,添加三个函数
一个是读取通道1光敏电阻的数据;
一个是读取通道3的电压;
一个是输出DA的数据。。

5V的AD DA。
如果读入的电压是5V,输入AD,就是255;
如果是0V,就是00000000;
如果是2.5V,就是125.
有个比例。

步骤,注意是
pcf8591A/D转换时:可以将连接在芯片上的AIN0,AIN1,AIN3,AIN2通道等的模拟量转换为数字量。

而且PCF8591芯片是一个8位的,通道上的电压取值范围是0-5v,相当于0-255一共256个刻度把5v平均分成了255份,那么1v电压对应的数字量就是51。所以我们在进行ad转换的时候不能简单的把读取到的量显示在数码管显示上,比如现在某个通道是3.1v的,那么它通过pcf8591芯片读取转换之后,我们实际上读取到的是3.1*51=158.1,但是如果题目要求显示电压值的话,我们就需要再把读取出来的数字量给处理一下,比如除以一个51.0。

从机等待应答部分的代码(即留下空格的部分)可省略。

PCF8591芯片D/A转换时(即把数字量转换为模拟量)在这里插入代码片

unsigned char read_in1()
{
	unsigned char dat;

  IIC_Start();		 //总线起始信号
 IIC_SendByte(0x90); //字节写地址
 IIC_WaitAck();		 //等待应答
 IIC_SendByte(0x01); //发送控制字
 IIC_WaitAck();
 
 IIC_Start(); 
 IIC_SendByte(0x91); //字节读地址
 IIC_WaitAck();
 dat=IIC_RecByte();
 IIC_SendAck(1); 
 IIC_Stop(); 
	
 return   dat;                  //处理读到的AIN的量
}
unsigned char read_in3()
{
	unsigned char dat;

  IIC_Start();		 //总线起始信号
 IIC_SendByte(0x90); //字节写地址
 IIC_WaitAck();		 //等待应答
 IIC_SendByte(0x03); //发送控制字
 IIC_WaitAck();
 
 IIC_Start(); 
 IIC_SendByte(0x91); //字节读地址
 IIC_WaitAck();
 dat=IIC_RecByte();
 IIC_SendAck(1); 
 IIC_Stop(); 
	
 return   dat;                  //处理读到的AIN的量
}

void write_dac(unsigned int dat)
{
   IIC_Start();
 IIC_SendByte(0x90);  //pcf8591写操作地址
 
 IIC_SendByte(0x40);  //选择dac输出通道,第6位为1打开D/A
 
 IIC_SendByte(dat);	  //选择要给pcf8591芯片的数字量
 
  IIC_WaitAck();	    
 IIC_Stop();   	      //停止通讯
}

全部代码啊

主函数的代码

#include <stc15.h>
#include <intrins.h>
#include <iic.h>

//接口
sbit S7=P3^0;
sbit S6=P3^1;
sbit S5=P3^2;
sbit S4=P3^3;
//宏定义
#define     LED       4   //定义主时钟
#define     ULN       5   //定义主时钟
#define     COM       6   //定义主时钟
#define     ABC       7   //定义主时钟
typedef     unsigned char   u8;
typedef     unsigned int    u16;
typedef     unsigned long   u32;
//-----------------------------------------------

#define FOSC 11059200L

#define T1MS (65536-FOSC/1000)      //1T模式
//#define T1MS (65536-FOSC/12/1000) //12T模式

//全局变量
u8 LEDbuf=0xFF;
u8 ULNbuf=0x00;
u8 SMGbuf[20];
u8 SMGdat[8];//8个数码管,所以8个元素

u32 tim1ms=0;//u32类型,几十天才溢出
/*************  本地常量声明   ,这是共阴的 **************/
u8 code table[]={                       //标准字库
//   0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
    0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
//black  -     H    J    K    L    N    o   P    U     t    G    Q    r   M    y
    0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
    0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46};    //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1

u8 code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};      //位码
//函数声明
void delayms(u16 tms);
void Delay1ms();		//@11.0592MHz
void sel(u8 x); //选择四个分支哪一个?
void sysinit();//系统初始化,关闭所有的外部设备
void disp();
//主函数
void main()
{
	//main局部变量
	u8 num1=25;
	u8 num2=0;
	int num3=1289;
	int num4=0;
	int num4H,num4L;//低位和高位
	
	u8 in1dat;
	u8 in3dat;
	
	//外设初始化
	  sysinit();
	//系统定时器初始化
	  AUXR |= 0x40;                   //定时器1为1T模式
    TMOD = 0x00;                    //设置定时器为模式0(16位自动重装载)
    TL1 = T1MS;                     //初始化计时值
    TH1 = T1MS >> 8;
    TR1 = 1;                        //定时器1开始计时
    ET1 = 1;                        //使能定时器0中断
    EA = 1;
	//大循环
	
	//这里,可以加一点测试代码,测试是不是每个外设都成功;
  	  SMGdat[0]=0x77;
			SMGdat[1]= table[num1/10];
			SMGdat[2]= table[num1%10];
			SMGdat[3]=0x40;
			SMGdat[4]=0x40;
			SMGdat[5]= 0x7C;		
			SMGdat[6]= table[0];
			SMGdat[7]= table[0];

	while(1)
	{
	  if(S7==0)
		{
			delayms(10);
			if(S7==0)
			{
				write24byte(0x00,num1);
				delayms(5);  //等待5ms,等待写入完成
			}
			while(S7==0);

		}
		
		else  if(S6==0)
		{
			delayms(10);
			if(S6==0)
			{
			  num2=read24byte(0x00)+20;
				delayms(5);
			}
		  while(S6==0);
		
			SMGdat[0]=0x77;
			SMGdat[1]= table[num1/10];
			SMGdat[2]= table[num1%10];
		  SMGdat[3]=0x40;
			SMGdat[4]=0x40;
			SMGdat[5]= 0x7C;		
			SMGdat[6]= table[num2/10];
			SMGdat[7]= table[num2%10];
		}
		
		if(S5==0)
	{
	  	delayms(10);
			if(S5==0)
			{
				
			 	write24byte(0x03,num3>>8); //写高8位到0x03
				delayms(5);  //等待5ms,等待写入完成
				write24byte(0x04,num3);//写低八位到0x04
				delayms(5);  //等待5ms,等待写入完成
			}
			while(S5==0);//松开按键
	}
	
	else	if(S4==0)
	{
	  	delayms(10);
			if(S4==0)
			{
			//读取int类型数据,读取高位,乘以256,再读取低位	
			 	num4H=read24byte(0x03);
				delayms(5);
				num4L=read24byte(0x04);
				delayms(5);
	
				num4=num4H*256+num4L;//将低位和高位合并起来
			}
			while(S4==0);//松开按键
			
			//分解出个位,十位,百位,千位的方法
			SMGdat[0]= table[num3/1000%10];
			SMGdat[1]= table[num3/100%10];
			SMGdat[2]= table[num3/10%10];
		  SMGdat[3]=table[num3%10];
			
			SMGdat[4]=table[num4/1000%10];;
			SMGdat[5]=table[num4/100%10];;
			SMGdat[6]= table[num4/10%10];;
			SMGdat[7]= table[num4%10];
	}	
	
	  if(tim1ms%500==0)  //500ms读取一次数据,刷新数据
		{
		    in1dat=read_in1();
	     in3dat=read_in3();
		}
	 
	
		 SMGdat[0]= 0x00;
			SMGdat[1]= table[in1dat/100%10];
			SMGdat[2]= table[in1dat/10%10];
		  SMGdat[3]=table[in1dat%10];
			
			SMGdat[4]=0x00;
			SMGdat[5]=table[in3dat/100%10];
			SMGdat[6]= table[in3dat/10%10];
			SMGdat[7]= table[in3dat%10];

	}
	
	
	
}

//函数定义
//-----------------------------------------------

/* Timer1 interrupt routine */
void tm1_isr() interrupt 3 using 1
{
    
	  tim1ms++;
	  disp();//1ms显示一次数码管
}
void Delay1ms()		//@11.0592MHz
{
	unsigned char i, j;

	_nop_();
	_nop_();
	_nop_();
	i = 11;
	j = 190;
	do
	{
		while (--j);
	} while (--i);
}

void delayms(u16 tms)
{
	u16 i=0;
	for(i=0;i<tms;i++)
	{
		  Delay1ms();
	}
}

void sel(u8 x)  //选择四个分支哪一个?
{
	//背下来了吗?
	switch(x)
	{
		case 0:P2=P2&0x1F;break;
		case LED:P2=P2&0x1F|0x80;break;
		case ULN:P2=P2&0x1F|0xA0;break;
		case COM:P2=P2&0x1F|0xC0;break;
		case ABC:P2=P2&0x1F|0xE0;break;
	}
}
void sysinit()//系统初始化,关闭所有的外部设备
{
	sel(LED);LEDbuf=0xFF;P0=LEDbuf;sel(0);
  sel(ULN);ULNbuf=0x00;P0=ULNbuf;sel(0);
	sel(COM);P0=0x00;sel(0);
	sel(ABC);P0=0xFF;sel(0);
}


void disp()
{
	//背下来
	static u8 i=0;
	//消隐
	sel(COM);P0=0x00;sel(0);
	sel(ABC);P0=0xFF;sel(0);
//显示
	sel(COM);P0=T_COM[i];sel(0);
	sel(ABC);P0=~SMGdat[i];sel(0);
	
	i++;
	if(i>=8)i=0;
}


 

iic.c

/*
  程序说明: IIC总线驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT107单片机综合实训平台 8051,12MHz
  日    期: 2011-8-9
*/

#include "stc15.h"
#include "intrins.h"
#include "iic.h"

#define DELAY_TIME 5

#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1

//总线引脚定义
sbit SDA = P2^1;  /* 数据线 */
sbit SCL = P2^0;  /* 时钟线 */

void IIC_Delay(unsigned char i)
{
    do{_nop_();}
    while(i--);        
}
//总线启动条件
void IIC_Start(void)
{
    SDA = 1;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SDA = 0;
    IIC_Delay(DELAY_TIME);
    SCL = 0;	
}

//总线停止条件
void IIC_Stop(void)
{
    SDA = 0;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SDA = 1;
    IIC_Delay(DELAY_TIME);
}

//发送应答
void IIC_SendAck(bit ackbit)
{
    SCL = 0;
    SDA = ackbit;  					// 0:应答,1:非应答
    IIC_Delay(DELAY_TIME);
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SCL = 0; 
    SDA = 1;
    IIC_Delay(DELAY_TIME);
}

//等待应答
bit IIC_WaitAck(void)
{
    bit ackbit;
	
    SCL  = 1;
    IIC_Delay(DELAY_TIME);
    ackbit = SDA;
    SCL = 0;
    IIC_Delay(DELAY_TIME);
    return ackbit;
}

//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
    unsigned char i;

    for(i=0; i<8; i++)
    {
        SCL  = 0;
        IIC_Delay(DELAY_TIME);
        if(byt & 0x80) SDA  = 1;
        else SDA  = 0;
        IIC_Delay(DELAY_TIME);
        SCL = 1;
        byt <<= 1;
        IIC_Delay(DELAY_TIME);
    }
    SCL  = 0;  
}

//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
    unsigned char i, da;
    for(i=0; i<8; i++)
    {   
    	SCL = 1;
	IIC_Delay(DELAY_TIME);
	da <<= 1;
	if(SDA) da |= 1;
	SCL = 0;
	IIC_Delay(DELAY_TIME);
    }
    return da;    
}

unsigned char read24byte(unsigned char addrtemp)
{
	  unsigned char temp;
    IIC_Start();
    IIC_SendByte(SlaveAddrW); //是地址
    IIC_WaitAck();
    IIC_SendByte(addrtemp);
    IIC_WaitAck();
    IIC_Start();
    IIC_SendByte(SlaveAddrR); //读地址
    IIC_WaitAck();
    temp = IIC_RecByte();
    IIC_SendAck(1);          //send no ACK
    IIC_Stop();
	return temp;
}
void write24byte(unsigned char addrtemp,unsigned char datatemp)
{
    IIC_Start();
    IIC_SendByte(SlaveAddrW);
    IIC_WaitAck();
    IIC_SendByte(addrtemp);
    IIC_WaitAck();
    IIC_SendByte(datatemp);    
    IIC_WaitAck();
    IIC_Stop();
}

unsigned char read_in1()
{
	unsigned char dat;

  IIC_Start();		 //总线起始信号
 IIC_SendByte(0x90); //字节写地址
 IIC_WaitAck();		 //等待应答
 IIC_SendByte(0x01); //发送控制字
 IIC_WaitAck();
 
 IIC_Start(); 
 IIC_SendByte(0x91); //字节读地址
 IIC_WaitAck();
 dat=IIC_RecByte();
 IIC_SendAck(1); 
 IIC_Stop(); 
	
 return   dat;                  //处理读到的AIN的量
}
unsigned char read_in3()
{
	unsigned char dat;

  IIC_Start();		 //总线起始信号
 IIC_SendByte(0x90); //字节写地址
 IIC_WaitAck();		 //等待应答
 IIC_SendByte(0x03); //发送控制字
 IIC_WaitAck();
 
 IIC_Start(); 
 IIC_SendByte(0x91); //字节读地址
 IIC_WaitAck();
 dat=IIC_RecByte();
 IIC_SendAck(1); 
 IIC_Stop(); 
	
 return   dat;                  //处理读到的AIN的量
}

void write_dac(unsigned int dat)
{
 IIC_Start();
 IIC_SendByte(0x90);  //pcf8591写操作地址
 IIC_SendByte(0x40);  //选择dac输出通道,第6位为1打开D/A
 IIC_SendByte(dat);	  //选择要给pcf8591芯片的数字量
 IIC_WaitAck();	    
 IIC_Stop();   	      //停止通讯
}

iic.h

#define __IIC_H

void IIC_Start(void); 
void IIC_Stop(void);  
bit IIC_WaitAck(void);  
void IIC_SendAck(bit ackbit); 
void IIC_SendByte(unsigned char byt); 
unsigned char IIC_RecByte(void); 

unsigned char read24byte(unsigned char addrtemp);
void write24byte(unsigned char addrtemp,unsigned char datatemp);

unsigned char read_in1();
unsigned char read_in3();
void write_dac(unsigned int dat);
	
#endif

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

05 比特币价格的含义

2009年1月&#xff0c;在赫尔辛基的一台小型服务器上&#xff0c;「中本聪」创建了一份简陋的开源代码&#xff0c;比特币的首个区块在这一天诞生。自此之后的十余年间&#xff0c;比特币和以其为代表作的区块链技术&#xff0c;踏上了波谲云诡的大航海征途。比特币的价格是指比…

Android---进程间通信机制3

1 服务如何注册到 SM 中 getIServiceManager().addService(name, service, false); getIServiceManger --- new ServiceManagerProxy(new BinderProxy()) BinderInternal.getContextObject --- 返回 BinderProxy 对象 ProcessState::self()->getContextObject: 创建一个 BpB…

k8s学习之路 | Day19 k8s 工作负载 Deployment(上)

文章目录1. Deployment 基础1.1 什么是 Deployment1.2 简单体验 Deployment1.3 Deployment 信息描述1.4 如何编写 Deployment2. Deployment 简单特性2.1 赋予 Pod 故障转移和自愈能力2.2 更新 Deployment2.3 回滚 Deployment2.4 暂停、恢复 Deployment 的上线过程2.5 Deploymen…

Gateway网关选型

网关一般分为流量网关和业务网关&#xff0c;流量网关负责接入所有的流量&#xff0c;并分发给不同的子系统&#xff0c;那在具体的业务接入之前&#xff0c;还有一层业务网关。流量网关提供全局性的、与后端业务应用无关的策略&#xff0c;例如 HTTPS证书卸载、Web防火墙、全局…

【教学典型案例】01.redis只管存不管删除让失效时间删除的问题

目录一&#xff1a;背景介绍二&#xff1a;redis1&#xff09;redis数据类型①String&#xff08;字符串&#xff09;②Hash&#xff08;哈希&#xff09;③List&#xff08;列表&#xff09;④Set&#xff08;集合&#xff09;2)缓存同步①设置有效期②同步双写③异步通知3&am…

java实现UDP及TCP通信

简介UDP(User Datagram Protocol)用户数据报协议&#xff0c;TCP(Transmission Control Protocol) 传输控制协议&#xff0c;是传输层的两个重要协议。UDP是一种无连接、不可靠传输的协议。其将数据源IP、目的地IP和端口封装成数据包&#xff0c;不需要建立连接&#xff0c;每个…

引用是否有地址的讨论的

说在前头&#xff0c;纯属个人理解&#xff0c;关于引用是否有地址&#xff0c;实际上并没有一个很统一的说法&#xff0c; C标准没有规定一个引用是否需要占用一块内存。 这里引用知乎“C 中引用是一块内存的标记&#xff0c;那引用本身有地址吗_百度知道 (baidu.com)”里面的…

Python爬虫之Js逆向案例(17)- Scrapy JD版店铺详情|问答

本案例是案例(16)的Scrapy版本 一次运行程序&#xff0c;同时获取内容&#xff1a;获取商店详情、商品问题、商品答案&#xff1b; 效果如下图&#xff1a; 一.Scrapy框架从安装到运行的过程 1.安装scrapy框架 控制台输入&#xff1a;pip3 install scrapy 2.验证安装结…

基于Flink CDC datastream mysql to mysql 序列化sql 数据同步

基于Flink CDC datastream mysql to mysql 序列化sql 数据同步 Flink CDC有两种方式同步数据库&#xff1a; 1. 一种是通过FlinkSQL直接输入两表数据库映射进行数据同步&#xff0c;缺点是只能单表进行同步&#xff1b; 2. 一种是通过DataStream开发一个maven项目&#xff0c…

华为机试题:HJ106 字符逆序(python)

文章目录&#xff08;1&#xff09;题目描述&#xff08;2&#xff09;Python3实现&#xff08;3&#xff09;知识点详解1、input()&#xff1a;获取控制台&#xff08;任意形式&#xff09;的输入。输出均为字符串类型。1.1、input() 与 list(input()) 的区别、及其相互转换方…

面试+算法:罗马数字及Excel列名与数字互相转换

概述 算法是一个程序员的核心竞争力&#xff0c;也是面试最重要的考查环节。 试题 判断一个罗马数字是否有效 罗马数字包含七种字符&#xff1a;I&#xff0c;V&#xff0c;X&#xff0c;L&#xff0c;C&#xff0c;D和M&#xff0c;如下 字符数值I1V5X10L50C100D500M1000…

libgdx导入blender模型

具体就是参考 官网 https://libgdx.com/wiki/graphics/3d/importing-blender-models-in-libgdx blender 教程可以看八个案例教程带你从0到1入门blender【已完结】 这里贴一下过程图。 1.初始环境搭建略过。 2.打开blender 选中摄像机和灯光&#xff0c;右键进行删除。 3.选中…

ES 7.7.0 数据迁移

本文使用 elasticdump 做数据迁移&#xff0c;支持在线和离线俩种方式&#xff0c;适用于数据量比较小的情况。 1、Node 安装 由于elasticdump 依赖于 node&#xff0c;首先需要安装下node。 1.1、 Linux 安装 $ wget https://nodejs.org/dist/v10.15.0/node-v10.15.0-linu…

[数据结构]:10-二叉排序树(无头结点)(C语言实现)

目录 前言 已完成内容 二叉排序树实现 01-开发环境 02-文件布局 03-代码 01-主函数 02-头文件 03-BinarySearchTreeCommon.cpp 04-BinarySearchTreeFunction.cpp 结语 前言 此专栏包含408考研数据结构全部内容&#xff0c;除其中使用到C引用外&#xff0c;全为C语言…

基于支持向量机SVM的房价预测,基于支持向量机SVM的回归分析

目录 支持向量机SVM的详细原理 SVM的定义 SVM理论 SVM应用实例,基于SVM的房价预测 支持向量机SVM的详细原理 SVM的定义 支持向量机(support vector machines, SVM)是一种二分类模型,它的基本模型是定义在特征空间上的间隔最大的线性分类器,间隔最大使它有别于感知机;…

【算法题】1958. 检查操作是否合法

插&#xff1a; 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 坚持不懈&#xff0c;越努力越幸运&#xff0c;大家一起学习鸭~~~ 题目&#xff1a; 给你一个下标从 0 开始的 8 x 8 网…

Vue响应式原理————Object.defineProperty()和proxy的用法分享

Vue框架一个比较核心的功能就是我们的数据是响应式的&#xff0c;这样我们在修改数据的时候&#xff0c;页面会自动帮我们更新&#xff0c;那么想要实现这个功能就要实现对一个数据的劫持&#xff0c;即在取值和设置值的同时我们能够检测到即数据劫持。vue2响应式的实现原理所依…

用原生js手写分页功能

分页功能如下&#xff1a; 数据分页显示&#xff0c;每页显示若干条数据&#xff0c;默认当前页码为第一页。例如&#xff1a;每页5条数据&#xff0c;则第一页显示 1-5 条&#xff0c;第二页显示 6-10 条&#xff0c;依此类推。当页码为第一页时&#xff0c;上一页为禁用状态…

IronPDF for .NET 2023.2.4 Crack

适用于 .NET 2023.2.4 的 IronPDF 添加对增量 PDF 保存的支持。 2023 年 3 月 2 日 - 10:23新版本 特征 添加了对 IronPdfEngine Docker 的支持。 添加了对增量 PDF 保存的支持。 重新设计了 PDF 签名和签名。 删除了 iTextSharp 依赖项。 在文本页眉/页脚中添加了 DrawDivider…

laravel8多模块、多应用和多应用路由

1、安装多应用模块 composer require nwidart/laravel-modules2、执行命令&#xff0c;config文件夹下生成一个modules.php配置文件 php artisan vendor:publish --provider"Nwidart\Modules\LaravelModulesServiceProvider"3、修改config文件夹下的modules.php&am…