摘要:对于电压或者电流连续变化的信号,就需要通过模数转换电路,变成单片机可以识别的数字电平信号。目前来说,常见的有两种方式,一种是并行比较,一种是逐次比较。具有成本低元件简单等优势,而且容易做出高精度的转换器,所以被广泛使用。
模拟量—>数字量(ADC模块)
5V 单片机 CPU 电路是二进制的,运算过程中,电压只有2种:高电平 5V 和低电平 0V 。对于电压或者电流连续变化的信号,就需要通过模数转换电路,变成单片机可以识别的数字电平信号。 MP3 就是用 ADC 采样保存的失真文件。
模拟量变成数字量,通常都是用比较器来负责转换。目前来说,常见的有两种方式,一种是并行比较,一种是逐次比较。
**并行比较器:**速度比较快,但是采用的元件非常非常多。成本会非常高。所以,实用性不是很广泛
**逐次比较器:**通过反馈控制,多次运算后,转换出结果。具有成本低、元件简单等优势,而且容易做出高精度的转换器,所以被广泛使用。
先来玩个游戏 :狗蛋拿了些花生米,跟你说,想吃就要先猜对有多少个。告诉你最多是 255 颗,你猜的时候,可以告诉你多了或者少了。那么,怎么猜才能最快猜出花生米的数量?
猜的时候,为了方便计算, 我们多加 0.5 颗花生米。
==第一步:==猜 255 ÷ 2 +0.5=128. 狗蛋告诉你,多了 (0) 。
第二步:猜 128 ÷ 2=64. 狗蛋告诉你,少了 (1)。
第三步:猜 (128 + 64) ÷ 2=96. 狗蛋 告诉 你,多了 (0) 。
第四步:猜 (96 + 64) ÷ 2=80. 狗蛋 告诉 你,少了 (1) 。
第五步:猜 (96 + 80) ÷ 2=88. 狗蛋 告诉 你,少了(1)。
第六步:猜 (96 + 88) ÷ 2=92. 狗蛋 告诉 你,多了(0)。
第七步:猜 (92+ 88) ÷ 2=90. 狗蛋 告诉 你,多了(0) 。
第八步:猜 (90+ 88) ÷ 2=89. 狗蛋 告诉 你,猜对 (?) 。
得出结果: 如果不加 0.5 ,实际计算公式得结果是 88.65234375 。实际上88.65比89小所以是 1
四舍五入, 89>88.65, 取 ?= 1 ;得出结果就是 0 1 0 1 1 0 0 1 =89=0x59;
1.ADC口配置成ADC输入模式或者高阻模式
2.ADC控制寄存器:ADC_CONTR.控制电源,转换速度,标志位,启动位,通道选择[2:0]
3.ADC采样结果输出寄存器ADC_RES,ADC_RESL。可以是[1:0]+[7:0],也可以是[7:0]+[1:0].
4.ADC转换,跟中断有关的寄存器IE
5.辅助寄存器AUXR1,主要是控制结果寄存器的存储格式
我是准备用ADC0来检测电池电压的,具体看老师需求,然后把示数显示到数码管上面,因为之前我出过数码管博客,大家可能还有点印象,不知道的看真正的数码管
//ADC初始化void ADC_Init(){ P1M1 |= 0x0f; P1M0 &= ~0x0f;//P1.0脚ADC0 P1ASF |= 0x0f;// P1M1 |= 0x02;// P1M0 &= ~0x02;//P1.1脚ADC1// P1ASF |= 0x02; CLK_DIV |= 0x20; ADC_RES = 0; ADC_RESL = 0;}
//ADC读数据底层驱动void ADC_Read_Data_Drive(){ //转换之前先把转换结果寄存器清零 ADC_RES = 0; ADC_RESL = 0; //启动转换 ADC_CONTR = 0x88;//转换速度我用最慢的 //等到ADC_FLAG为1 while(!(ADC_CONTR&0x10)); //然后把数据传到缓存变量里面去 ADC_Read_Data = ADC_RES<<8; ADC_Read_Data = ADC_Read_Data+ADC_RESL; }
采集电压
#include "all.h"//有数据那我们就得存u16 xdata ADC_Read_Data = 0;u16 xdata ADC_Filter_Data = 0;//ADC初始化void ADC_Init(){ P1M1 |= 0x0f; P1M0 &= ~0x0f;//P1.0脚ADC0 P1ASF |= 0x0f;// P1M1 |= 0x02;// P1M0 &= ~0x02;//P1.1脚ADC1// P1ASF |= 0x02; CLK_DIV |= 0x20; ADC_RES = 0; ADC_RESL = 0;}//ADC读数据底层驱动void ADC_Read_Data_Drive(){ //转换之前先把转换结果寄存器清零 ADC_RES = 0; ADC_RESL = 0; //启动转换 ADC_CONTR = 0x88;//转换速度我用最慢的 //等到ADC_FLAG为1 while(!(ADC_CONTR&0x10)); //然后把数据传到缓存变量里面去 ADC_Read_Data = ADC_RES<<8; ADC_Read_Data = ADC_Read_Data+ADC_RESL; }//全局的ADC滤波数据结构体指针ADC_Data* adc_filter;//ADC滤波数据底层驱动void ADC_Filter_Data_Drive(){ /*u16 ADC_Min = 0; u16 ADC_Max = 0; u16 ADC_Tmp = 0; u16 ADC_Result = 0;*/ //设置两个循环变量 u8 i = 0; u8 j = 0; ADC_Filter_Data = 0; ADC_Read_Data_Drive(); for(i = 0;i<4;i++)//外层8次循环 { adc_filter->ADC_Result = 0; adc_filter->ADC_Min = adc_filter->ADC_Max = ADC_Read_Data; for(j = 0;j<4;i++)//内层8次循环 { adc_filter->ADC_Tmp = ADC_Read_Data; if (adc_filter->ADC_Tmp < adc_filter->ADC_Min) { adc_filter->ADC_Result += adc_filter->ADC_Tmp; adc_filter->ADC_Min = adc_filter->ADC_Tmp; } else if (adc_filter->ADC_Tmp > adc_filter->ADC_Max) { adc_filter->ADC_Result += adc_filter->ADC_Tmp; adc_filter->ADC_Max = adc_filter->ADC_Tmp; } else { adc_filter->ADC_Result += adc_filter->ADC_Tmp; } } adc_filter->ADC_Result /= 4; ADC_Filter_Data += adc_filter->ADC_Result; } ADC_Filter_Data /= 4;}
#ifndef ADC_Drive#define ADC_Drivetypedef struct ADC_Filter_Data{ u16 ADC_Min; //ADC最小值 u16 ADC_Max; //ADC最大值 u16 ADC_Tmp; //ADC临时值 u16 ADC_Result; //ADC结果} ADC_Data;//外部声明extern void ADC_Init();extern void ADC_Read_Data_Drive();extern void ADC_Filter_Data_Drive();extern u16 xdata ADC_Read_Data;extern u16 xdata ADC_Filter_Data;#endif
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/124049.html
摘要:复位后初值是子函数调用,中断响应过程调用子函数处理中断响应的时候,程序计数器的值以及相关数据会先压入堆栈,然后去处理子函数中断服务。联动文章身家过亿的帝都富豪对小码农说你时空复杂度会了吗 ...
摘要:行列总共使用个口,可以扫描个按键的开关状态,这就是矩阵键盘的优势。口之间必须串联电阻。 文章目录 小码农为了总裁,咳咳,为了知识敢说按键不会吗?==**帝都富豪与...
摘要:否则可能会导致电平颠倒完美的计数糟糕的线条再来一个测试组我们来实现一个呼吸灯的效果呼吸灯波形为了贤淑妻子,咳咳,贤淑才女,小码农必定让控制时间什么是脉宽调制中间动的线是电流线,电流通断,电流小就暗,电流大就亮。 ...
摘要:目前,所有型号串口的输入是输出是。串口全双工通信是没有时钟脉冲的,只能依靠晶振脉冲定时器的溢出脉冲。中断中读取,清标志,然后返回给计算机,等待发送完毕防重叠最少时间次位定时器时间。实现烧录程序的目的。 ...
阅读 1219·2021-11-22 13:54
阅读 1405·2021-11-22 09:34
阅读 2646·2021-11-22 09:34
阅读 3906·2021-10-13 09:39
阅读 3321·2019-08-26 11:52
阅读 3318·2019-08-26 11:50
阅读 1495·2019-08-26 10:56
阅读 1880·2019-08-26 10:44