STC15系列P1.3做ADC-使用内部基准计算外部电压并串口打印
Posted perseverance52
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STC15系列P1.3做ADC-使用内部基准计算外部电压并串口打印相关的知识,希望对你有一定的参考价值。
【STC15系列】P1.3做ADC-使用内部基准计算外部电压并串口打印
-
程序从STC 官方STC15实验箱例程28修改来的,源代码是通过数码管显示,修改为串口打印输出。
-
采用的开发板x型号:
STC15F2K60S2
使用万用表实测基准电压P1.0端口为5.07V,所以我代码中定的基准就采用的5.07V为基准电压值。
- 采用的的是10K定位器接到到P1.3引脚上。
测量方式
自定义其中一种:
#define Cal_MODE 0 //每次测量只读1次ADC. 分辨率0.01V
// #define Cal_MODE 1 //每次测量连续读16次ADC 再平均计算. 分辨率0.01V
主程序代码
/*---------------------------------------------------------------------*/
/* --- STC MCU International Limited ----------------------------------*/
/* --- STC 1T Series MCU Demo Programme -------------------------------*/
/* 如果要在程序中使用此代码,请在程序中注明使用了宏晶科技的资料及程序 */
/*---------------------------------------------------------------------*/
/************* 本程序功能说明 **************
读ADC测量外部电压,使用内部基准计算电压.
用户可以修改宏来选择时钟频率.
用户可以在"用户定义宏"中选择共阴或共阳. 推荐尽量使用共阴数码管.
使用Timer0的16位自动重装来产生1ms节拍,程序运行于这个节拍下, 用户修改MCU主时钟频率时,自动定时于1ms.
右边4位数码管显示测量的电压值值.
外部电压从板上测温电阻两端输入, 输入电压0~VDD, 不要超过VDD或低于0V.
实际项目使用请串一个1K的电阻到ADC输入口, ADC输入口再并一个电容到地.
******************************************/
#include "stdio.h"
#include "STC15Fxxxx.H"
#include<USART.h>
/***********************************************************/
#define MAIN_Fosc 11059200L //定义主时钟
#define P1n_pure_input(bitn) P1M1 |= (bitn), P1M0 &= ~(bitn)
/****************************** 用户定义宏 ***********************************/
#define Cal_MODE 0 //每次测量只读1次ADC. 分辨率0.01V
// #define Cal_MODE 1 //每次测量连续读16次ADC 再平均计算. 分辨率0.01V
#define Timer0_Reload (65536UL -(MAIN_Fosc /5000)) //Timer 0 中断频率, 5000次/秒
/*****************************************************************************/
/************* 本地变量声明 **************/
bit B_5ms; //1ms标志
u16 msecond; //计时
u16 Bandgap; //
u16 Get_ADC10bitResult(u8 channel); //channel = 0~7
void delay_ms(unsigned int ms);
void Timer0Init(void) //5毫秒@11.0592MHz
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TH0 = (u8)(Timer0_Reload / 256); //设置定时初始值
TL0 =(u8)(Timer0_Reload % 256); //设置定时初始值
ET0 = 1; //Timer0 interrupt enable
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
EA = 1 ;
/**********************************************/
void main(void)
u8 i;
float Voltage = 0.0;
u16 j;
// P0M1 = 0; P0M0 = 0; //设置为准双向口
// P1M1 = 0; P1M0 = 0; //设置为准双向口
// P2M1 = 0; P2M0 = 0; //设置为准双向口
// P3M1 = 0; P3M0 = 0; //设置为准双向口
// P4M1 = 0; P4M0 = 0; //设置为准双向口
// P5M1 = 0; P5M0 = 0; //设置为准双向口
// P6M1 = 0; P6M0 = 0; //设置为准双向口
// P7M1 = 0; P7M0 = 0; //设置为准双向口
InitSerialPort(); //初始化串口,波特率9600,8bit数据位,1停止位,无校验
P1M1 |= (1<<3); // 把ADC口设置为高阻输入
P1M0 &= ~(1<<3);
P1ASF = (1<<3); //P1.3做ADC
ADC_CONTR = 0xE0; //90T, ADC power on
Timer0Init();//定时器0初始化
InitSerialPort(); //初始化串口,波特率9600,8bit数据位,1停止位,无校验
while(1)
if(B_5ms) //5ms到达标志位
B_5ms = 0;
if(++msecond >= 100) //计数到达100
msecond = 0;
#if (Cal_MODE == 0)
//=================== 只读1次ADC, 10bit ADC. 分辨率0.01V ===============================
P1ASF = 0;
Get_ADC10bitResult(0); //改变P1ASF后先读一次并丢弃结果, 让内部的采样电容的电压等于输入值.
Bandgap = Get_ADC10bitResult(0); //读P1.0的电压为基准ADC, P1ASF=0, 0通道的电压值
printf("\\t Bandgap =%u \\t\\n",Bandgap);
P1ASF = 1<<3;
j = Get_ADC10bitResult(3); //读外部电压ADC
j = (u16)((u32)j * 507 / Bandgap); //计算外部电压, Bandgap为5.07V, 测电压分辨率0.01V
#endif
//==========================================================================
//===== 连续读16次ADC 再平均计算. 分辨率0.01V =========
#if (Cal_MODE == 1)
P1ASF = 0;
Get_ADC10bitResult(0); //改变P1ASF后先读一次并丢弃结果, 让内部的采样电容的电压等于输入值.
for(j=0, i=0; i<16; i++)
j += Get_ADC10bitResult(0); //读内部基准ADC, P1ASF=0, 读0通道
Bandgap = j >> 4; //16次平均
P1ASF = (1<<3); //P1.3做ADC
for(j=0, i=0; i<16; i++)
j += Get_ADC10bitResult(3); //读外部电压ADC
j = j >> 4; //16次平均
j = (u16)((u32)j * 507 / Bandgap); //计算外部电压, Bandgap为5.07V, 测电压分辨率0.01V
#endif
//==========================================================================
printf("\\t AD_Value =%u \\t",j);
Voltage =(j/1023.0)*5*2.046;
printf("Voltage:%3.2fV \\r\\n",Voltage);
// delay_ms(500);
/**********************************************/
//========================================================================
// 函数: u16 Get_ADC10bitResult(u8 channel)
// 描述: 查询法读一次ADC结果.
// 参数: channel: 选择要转换的ADC.
// 返回: 10位ADC结果.
// 版本: V1.0, 2012-10-22
//========================================================================
u16 Get_ADC10bitResult(u8 channel) //channel = 0~7
ADC_RES = 0;
ADC_RESL = 0;
ADC_CONTR = (ADC_CONTR & 0xe0) | 0x08 | channel; //start the ADC
NOP(4);
while((ADC_CONTR & 0x10) == 0) ; //wait for ADC finish
ADC_CONTR &= ~0x10; //清除ADC结束标志
return (((u16)ADC_RES << 2) | (ADC_RESL & 3));
//========================================================================
// 函数: void delay_ms(unsigned char ms)
// 描述: 延时函数。
// 参数: ms,要延时的ms数, 自动适应主时钟.
// 返回: none.
// 版本: VER1.0
// 日期: 2013-4-1
// 备注:
//========================================================================
void delay_ms(unsigned int ms)
unsigned int i;
do
i = MAIN_Fosc / 13000;
while(--i) ; //14T per loop
while(--ms);
/********************** Timer0 1ms中断函数 ************************/
void timer0 (void) interrupt TIMER0_VECTOR
B_5ms = 1; //1ms标志
- USART.c
/*----------------------------------------------------------
* 项目名称:
串口通信驱动程序
* 功能描述:
1、串口初始化
2、查询法接收一个字节
3、串口发送一个字节
4、串口发送一个字符串
5、串口中断方式接收一个字符
* 配置说明:
MCU: STC15F2K60S2
开发板: STC15F2K60S2开发板
晶振: 外部时钟:11.0592MHz
扩展模块: -10K可调定位器
* 备注:
- 将开发板的串口与电脑串口连接
----------------------------------------------------------*/
#include "STC15Fxxxx.H"
//#include<STC15W.h>
#include<USART.h>
unsigned char *pchar; //定义一个全局指针
#define FOSC 11059200L //系统频率
#define BAUD 9600 //串口波特率
//----------------------------------------------------------
// 函数名称:void IniSerialPort(void)
// 函数功能:串口初始化
//----------------------------------------------------------
void InitSerialPort(void)
SCON = 0x50; //8位数据,可变波特率
// AUXR |= 0x01; //为1时串口波特率发生器为定时器2,否则默认定时器1
// AUXR |= 0x04; //定时器时钟为Fosc,1T模式,否则12分频
// T2L = 0xE0; //定时器初值,内部时钟11.0592M,波特率9600
// T2H = 0xFE; //定时器初值
T2L = (65536 - (FOSC/4/BAUD)); //设置波特率重装值
T2H = (65536 - (FOSC/4/BAUD))>>8;
// AUXR |= 0x10; //启动定时器(为1定时器2开始计数,为0停止)
AUXR = 0x15; //替代:39-40,45行代码
//ES=1; //串口中断开关,采用查询法时不用打开中断
REN=1; //串口为工作方式1,允许接收数据
SM0=0; //SM0 SM1串口工作方式选择,01:8位异步收发,波特率由定时器决定
SM1=1;
//----------------------------------------------------------
// 函数名称:unsigned char ReceiveByte(void)
// 函数功能:查询法接收一个字节
//----------------------------------------------------------
unsigned char ReceiveByte(void)
unsigned char rbyte;
while(!RI); //查询接收标志位,是否有数据到达缓冲区
RI=0; //清零接收标志位
rbyte=SBUF; //从缓冲区读取数据
return rbyte;
//----------------------------------------------------------
// 函数名称:void SendByte(unsigned char sbyte)
// 函数功能:串口发送一个字节
//----------------------------------------------------------
void SendByte(unsigned char sbyte)
SBUF=sbyte; //发送数据
while(!TI); //等待发送完成
TI=0; //清零发送标志位
//----------------------------------------------------------
// 函数名称:void SendString(unsigned char *pstr)
// 函数功能:串口发送一个字符串
//----------------------------------------------------------
void SendString(unsigned char *pstr)
while(*pstr!='\\0') //字符串是否发完
SendByte(*pstr); //发送字符串数据
pstr++; //指向下一个字符
//----------------------------------------------------------
// 函数名称:void SerialPortInte(void)
// 函数功能:串口中断方式接收一个字符
//----------------------------------------------------------
void SerialPortInte(void) interrupt 4
RI=0; //清零接收标志位
*pchar=SBUF; //读取缓冲区的数据
//重写putchar函数
char putchar(unsigned char c)
SendByte(c);
return c;
/**********************************THE END**********************************/
程序源码
链接:https://pan.baidu.com/s/1JHY9k1IIPOlxEakZVcp08g
提取码:3322
以上是关于STC15系列P1.3做ADC-使用内部基准计算外部电压并串口打印的主要内容,如果未能解决你的问题,请参考以下文章