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-使用内部基准计算外部电压并串口打印的主要内容,如果未能解决你的问题,请参考以下文章

STC15比较器做ADC程序示例

STC15W408AS单片机通过ADC端口采集模拟量并从串口打印数值

STC15比较器介绍以及比较器中断方式作为掉电检测示例程序

STC15系列PWM相关功能寄存器介绍

STC15读取内部ID示例程序

利用基准电压效正Vcc做参考电压的ADC采样计算方法