/*---------------------------------------------------------------------*/
/* --- STC15W408AS-SOP16 通过BandGap电压精确测量外部输入电压C程序 -----*/
/* History:
1.改Vx单次测量结果为多次平均测量结果.
2.将BandGap电压值的获取方法从指针改回到绝对地址变量.
3.增加BandGap电压值(Vbg_RAM,Vbg_ROM)的数码管显示输出,精确到1mv.
4.不同芯片跑相同程序测量结果会有差异,同一芯片在不同晶振频率或不同A/D转
换速度下测量结果也有差异,为此增加系统校准参数c2,c1,c0.需自行校准.
方法:等间隔测量几个电压值,拟合基准值与测量值使误差最小,求得c2,c1,c0.
Vc=c2*Vx*Vx+c1*Vx+c0.其中,基准值由精度更高的仪表测量.
缺省:(12MHz,ADC_SPEEDLL,5AVG,c2=0,c1=1,c0=0)
*/
//说明:
// ADC的第9通道是用来测试内部BandGap参考电压的,由于内部BandGap参考电
//压很稳定,不会随芯片的工作电压的改变而变化,所以可以通过两次测量和一次计算
//便可得到外部的精确电压.公式如下:
//ADCbg / Vbg = 1023 / VCC
//ADCx / Vx = 1023 / VCC
//由于两次测量的时间间隔很短,VCC的电压在此期间的波动可忽略不计
//从而可推出 ADCbg / Vbg = ADCx / Vx
//进一步得出 Vx = Vbg * ADCx / ADCbg
//其中:ADCbg为Bandgap电压的ADC测量值
// Vbg为实际Bandgap的电压值,在单片机进行CP测试时记录的参数,单位为毫伏(mV)
// ADCx为外部输入电压的ADC测量值
// Vx外部输入电压的实际电压值,单位为毫伏(mV)
//
//具体的测试方法:首先将P1ASF初始化为0,即关闭所有P1口的模拟功能
//然后通过正常的ADC转换的方法读取第0通道的值,即可通过ADC的第9通道读取当前
//内部BandGap参考电压值ADCbg,然后测量有外部电压输入的ADC通道,测量出
//外部输入电压的ADC测量值ADCx,接下来从RAM区或者ROM区读取实际Bandgap的电压值Vbg,
//最后通过公式Vx = Vbg * ADCx / ADCbg,即可计算出外部输入电压的实际电压值Vx
//-----------------------------------------
//通过"_at_"关键字定义绝对(起始)地址变量Vbg_RAM或者Vbg_ROM,
//该地址在RAM区或者ROM区预存有标定的BandGap电压值Vbg(单位:毫伏mv)
unsigned int idata Vbg_RAM _at_ 0xef; //对于只有256字节RAM的MCU存放地址为0EFH
//unsigned int idata Vbg_RAM _at_ 0x6f; //对于只有128字节RAM的MCU存放地址为06FH
//注意:需要在下载代码时选择"在ID号前添加重要测试参数"选项,才可在程序中获取此参数
//unsigned int code Vbg_ROM _at_ 0x03f7; // 1K程序空间的MCU
//unsigned int code Vbg_ROM _at_ 0x07f7; // 2K程序空间的MCU
//unsigned int code Vbg_ROM _at_ 0x0bf7; // 3K程序空间的MCU
//unsigned int code Vbg_ROM _at_ 0x0ff7; // 4K程序空间的MCU
//unsigned int code Vbg_ROM _at_ 0x13f7; // 5K程序空间的MCU
unsigned int code Vbg_ROM _at_ 0x1ff7; // 8K程序空间的MCU
//unsigned int code Vbg_ROM _at_ 0x27f7; //10K程序空间的MCU
//unsigned int code Vbg_ROM _at_ 0x2ff7; //12K程序空间的MCU
//unsigned int code Vbg_ROM _at_ 0x3ff7; //16K程序空间的MCU
//unsigned int code Vbg_ROM _at_ 0x4ff7; //20K程序空间的MCU
//unsigned int code Vbg_ROM _at_ 0x5ff7; //24K程序空间的MCU
//unsigned int code Vbg_ROM _at_ 0x6ff7; //28K程序空间的MCU
//unsigned int code Vbg_ROM _at_ 0x7ff7; //32K程序空间的MCU
//unsigned int code Vbg_ROM _at_ 0x9ff7; //40K程序空间的MCU
//unsigned int code Vbg_ROM _at_ 0xbff7; //48K程序空间的MCU
//unsigned int code Vbg_ROM _at_ 0xcff7; //52K程序空间的MCU
//unsigned int code Vbg_ROM _at_ 0xdff7; //56K程序空间的MCU
//unsigned int code Vbg_ROM _at_ 0xeff7; //60K程序空间的MCU
//-----------------------------------------
//#include <intrins.h> //_nop_()
extern void _nop_ (void);
//I/O定义
sfr P1 = 0x90; //1111,1111 端口1
sfr P3 = 0xB0; //1111,1111 端口3
sfr P5 = 0xC8; //xx11,1111 端口5
sfr P1M1 = 0x91; //PxM1.n,PxM0.n =00->Standard, 01->push-pull
sfr P1M0 = 0x92; // =10->pure input, 11->open drain
sfr P3M1 = 0xB1;
sfr P3M0 = 0xB2;
sfr P5M1 = 0xC9;
sfr P5M0 = 0xCA;
//ADC 特殊功能寄存器
sfr P1ASF = 0x9D; //P1口模拟功能控制寄存器
sfr ADC_CONTR = 0xBC; //A/D转换控制寄存器
sfr ADC_RES = 0xBD; //A/D转换结果高8位
sfr ADC_RESL = 0xBE; //A/D转换结果低2位
sfr CLK_DIV = 0x97; //时钟分频控制寄存器
#define ADRJ 0x20 //ADC转换结果调整寄存器位(sbit ADRJ = CLK_DIV^5)
#define ADC_POWER 0x80 //ADC电源控制位
#define ADC_SPEEDLL 0x00 //540个时钟周期A/D转换一次
#define ADC_SPEEDL 0x20 //360个时钟周期A/D转换一次
#define ADC_SPEEDH 0x40 //180个时钟周期A/D转换一次
#define ADC_SPEEDHH 0x60 // 90个时钟周期A/D转换一次
#define ADC_FLAG 0x10 //ADC完成标志
#define ADC_START 0x08 //A/D转换启动控制位
#define ADC_CHS 0x02 //选择模拟输入通道(0~7)
//三位共阴数码管管脚定义
sbit ledw1 = P1^1;
sbit ledw2 = P1^5;
sbit ledw3 = P5^4;
sbit leda = P1^3; //f aaaa b
sbit ledb = P5^5; //ff bb
sbit ledc = P3^3; //ff bb
sbit ledd = P3^7; // gggggg
sbit lede = P1^0; // gggggg
sbit ledf = P1^4; //ee cc
sbit ledg = P3^2; //ee cc dpdp
sbit leddp = P3^6; //e dddd c dpdp
void InitADC(); //初始化ADC
void InitLED(); //初始化数码管
void Delay(unsigned int n); //软件延时
unsigned int GetADCResult (unsigned char ch); //读取ADC结果
void ShowResult(float Vx); //显示测量结果(0~99.9)
void DecomNum(float Vx, unsigned char *d1, unsigned char *d2, unsigned char *d3);//分解输入浮点数为三个数码管显示数字
void NumCode(unsigned char digit); //七段数码管0~9数字编码
void main()
{
float ADCbg; //BandGap电压的ADC测量值
float ADCx; //外部输入电压的ADC测量值
float Vx; //外部输入电压的实际电压值,单位为毫伏(mV)
float Rs, Rl; //采样电阻和限流电阻
unsigned int k, nc = 5; //测量次数(nc)
float Va; //外部输入电压多次测量的平均值,单位为伏特(V)
//Vo =[1.250; 1.850; 2.500; 3.300; 4.190; 5.000; 6.24; 7.20; 8.40; 9.11; 10.40; 11.50]; //基准电压(FLUKE115C)
//Vc =[1.53; 2.17; 2.86; 3.71; 4.60; 5.50; 6.74; 7.67; 8.87; 9.54; 10.8; 11.8 ]; //校准前(SPEEDHH+33.1776MHz+10000AVG)
//Vc =[1.26; 1.85; 2.50; 3.30; 4.20; 5.03; 6.27; 7.18; 8.43; 9.14; 10.4; 11.5 ]; //校正后(SPEEDHH+33.1776MHz+10000AVG)(c2=0.007383,c1=0.8973,c0=-0.1308)
//Vo =[1.252; 1.982; 2.502; 3.320; 4.190; 5.000; 6.26; 7.20; 8.40; 9.24; 10.40; 11.19]; //基准电压(FLUKE115C)
//Vc =[1.25; 1.98; 2.51; 3.33; 4.20; 5.02; 6.28; 7.21; 8.42; 9.28; 10.4; 11.2 ]; //校准前(SPEEDLL+12MHz+7AVG)
float c2 = 0.0; //系统校准参数(根据需要校准),Vc=c2*Va*Va+c1*Va+c0
float c1 = 1.0; //系统校准参数(根据需要校准),Vc=c2*Va*Va+c1*Va+c0
float c0 = 0.0; //系统校准参数(根据需要校准),Vc=c2*Va*Va+c1*Va+c0
float Vc; //系统校准后的测量电压,Vc=c2*Va*Va+c1*Va+c0
P1M0=P1M1=P3M0=P3M1=P5M0=P5M1=0x00;
InitLED(); //初始化数码管
InitADC(); //初始化ADC
while (1)
{
Va = 0; //初始化0
for (k=0; k<nc; k++)
{
//第一步:通过ADC的第3通道测试外部输入电压的ADC测量值
P1ASF = 0x04; //设置P1.2口为模拟通道
ADCx = GetADCResult(2);
//第二步:通过ADC的第9通道测试BandGap电压的ADC测量值
P1ASF = 0x00; //不设置P1ASF,即可从ADC的第9通道读取内部BandGap电压的ADC测量值
ADCbg = GetADCResult(0);
//第三步:通过公式计算外部输入的实际电压值
Vx = Vbg_RAM * ADCx / ADCbg; //使用RAM中的BandGap电压参数进行计算
// Vx = Vbg_ROM * ADCx / ADCbg; //使用ROM中的BandGap电压参数进行计算
Rs = 0.994; //采样电阻(单位:千欧)
Rl = 10.03; //限流电阻(单位:千欧)
Vx = Vx/1e3*(Rl+Rs)/Rs; //根据采样电阻和限流电阻换算测量电压(单位:伏特V)
Va = Va+Vx/nc;
STC15W408AS-SOP16电压表源码.rar_SOP16_STC15W408电压表_hurried3x6_stc15w4
版权申诉
5星 · 超过95%的资源 192 浏览量
2022-07-15
12:22:37
上传
评论 3
收藏 8KB RAR 举报
weixin_42651887
- 粉丝: 76
- 资源: 1万+
最新资源
- 人工智能实验四 感知器算法的设计实现
- java小项目多线程多线程 复制文件 冒泡排序 群聊
- 四数之和(java代码).docx
- 701837906919458TapScanner v3.0.10 (Pro).apk
- 青岛大学人工智能实验二 利用α-β搜索的博弈树算法编写一字棋游戏
- ### 1、项目介绍 本项目Scrapy进行数据爬取,并使用Django框架+PyEcharts实现可视化大屏 效果如下:
- # 微信小程序-健康菜谱 基于微信小程序的一个查找检索菜谱的应用 ### 效果 !动态图(./res/gif/demo
- zabbix-get命令包资源
- 289ssm-mysql-jsp 计算机课程实验管理系统.zip(可运行源码+数据库文件+文档)
- 毕业设计,基于PyQt5实现的可视化界面的Python车牌自动识别系统源码
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
评论3