stc15系列p1.3做adc-使用内部基准计算外部电压并串口打印

perseverance52      2022-02-16     210

关键词:

【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读取内部id示例程序(代码片段)

...案例基于STC15F2K60S2为验证对象。📑STC15ID序列介绍STC15系列STC最新一代STC15系列单片机出厂时都具有全球唯一身份证号码(ID号)。最新STC15系列单片机的程序存储器的最后7个字节单元的值是全球唯一ID号,用户不可修改,... 查看详情

stc15比较器介绍以及比较器中断方式作为掉电检测示例程序(代码片段)

...较器中断方式作为掉电检测示例程序比较器介绍STC15W201S系列、STC15W404S系列及STC15W1K16S系列的比较器内部规划如下图所示:有ADC的单片机STC15W401AS系列及STC15W4K32S4系列的比较器内部规划如下图所示:比较器正极输入端CMP+电平... 查看详情

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

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

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

...并从串口打印数值0-1023数据采集STC15W408AS引脚功能图STC15系列单片机的A/D转换器A/D转换器的结构STC15系列单片机ADC由多路选择开关、比较器、逐次比较寄存器、10位DAC、转换结果寄存器(ADC_RES和ADC_RESL)以及ADC_CONTR构成。STC15系列... 查看详情

stc15系列单片机eeprom读写示例(代码片段)

STC15系列单片机EEPROM读写示例🌼STC15手册有关EEPROM描述🌾STC15系列单片机内部集成了大容量的EEPROM,其与程序空间是分开的。利用ISP/IAP技术可将内部DataFlash当EEPROM,擦写次数在10万次以上。EEPROM可分为若干个扇区&#... 查看详情

2.stc15w408as单片机时钟(代码片段)

...振荡产生的时钟。但对于无外部时钟源的单片机(STC15F100W系列、STC15W201S系列、STC15W404S系列、STC15W1K16S系列)以及现供货的STC15F2K60S2系列C版单片机,其主时钟只能是内部R/C时钟。        主时钟可在管脚MCLKO或MCLKO_2对外输出... 查看详情

stc15系列pwm相关功能寄存器介绍(代码片段)

STC15系列PWM相关功能寄存器介绍✨以下数据来源于stc15手册。📓增强型PWM波形发生器功能相关寄存器总表1.端口配置寄存器:P_SW22.PWM配青寄存器:PWMICFGCBTADC:PWM计数器归零时(CBIF==1时)触发ADC转换–0:PWM计数器归零时不... 查看详情

stc15系列之sdccstc15系列sdcc专用头文件内容分享(代码片段)

【STC15系列之SDCC】STC15系列SDCC专用头文件内容分享如果使用VSCodePlatformIO开发STC单片机,所提供的型号的头文件很有限,除非自己添加,像STC系列单片机一些型号的头文件还没有只能依赖8052头文件使用,而8052的头... 查看详情

stc15系列单片机利用eeprom统计开机次数(代码片段)

STC15系列单片机利用EEPROM统计开机次数📺测试效果:📌相关篇《STC15系列单片机EEPROM读写示例》✨采用的是无符号整数(unsignedint)变量计数方式,可统计次数位:65535,如果还觉得不够,还可以定义... 查看详情

stc15系列单片机利用eeprom统计开机次数(代码片段)

STC15系列单片机利用EEPROM统计开机次数📺测试效果:📌相关篇《STC15系列单片机EEPROM读写示例》✨采用的是无符号整数(unsignedint)变量计数方式,可统计次数位:65535,如果还觉得不够,还可以定义... 查看详情

stc15定时器0做9-16位pwm示例解读(代码片段)

【STC15】定时器0做9-16位PWM示例解读STC15资料包STC15系列库函数V1.0,2014:http://www.stcmcudata.com/STC-LIB/STC15-SOFTWARE-LIB-V1.0.rarTimer0-做9-16位PWM为例:功能说明以及PWM不同频率测试数据说明烧录验证单片机型号:IAP15F2K61S2PWM数据采样&#... 查看详情

stc15系列单片机教程之一:oneled

STC15系列单片机教程之一:OneLEDSTC15系列单片机教程之一:OneLED一、开发软件准备二、STC15F2K60S单片机IO分配三、程序编写1.Keil新建项目2.编写程序3.程序的编译四、固件下载总结本系列教程开始学习STC15系列单片机的C语言编程,读... 查看详情

10.stc15w408as单片机a/d转换器(代码片段)

        10.STC15W408AS单片机A/D转换器        STC15系列单片机内部集成了8路10位高速A/D转换器。STC15系列单片机的A/D转换口在P1口(P1.7-P1.0),有8路10位高速A/D转换器,速度到300KHz(30万次/秒)。8路电压输入型A/D,可做... 查看详情

stc15w408as系列管脚说明

STC15W401AS系列管脚说明STC15W408AS-35I-SKDIP28STC15W408AS-35I-DIP16STC15W408AS-35I-SOP20参考STC15说明书: 查看详情

10.stc15w408as单片机a/d转换器(代码片段)

        10.STC15W408AS单片机A/D转换器        STC15系列单片机内部集成了8路10位高速A/D转换器。STC15系列单片机的A/D转换口在P1口(P1.7-P1.0),有8路10位高速A/D转换器,速度到300KHz(30万次/秒)。8路电压输入型A/D,可做... 查看详情

10.stc15w408as单片机a/d转换器(代码片段)

        10.STC15W408AS单片机A/D转换器        STC15系列单片机内部集成了8路10位高速A/D转换器。STC15系列单片机的A/D转换口在P1口(P1.7-P1.0),有8路10位高速A/D转换器,速度到300KHz(30万次/秒)。8路电压输入型A/D,可做... 查看详情

9.stc15w408as单片机eeprom(代码片段)

        STC15系列单片机内部集成了大容量的EEPROM,与其程序空间是分开的。利用ISP/IAP技术可将内部DataFlash当EEPROM,擦写次数在10W次以上。EEPROM可分为若干个扇区,每个扇区包含512字节。使用时,建议同一次修... 查看详情

9.stc15w408as单片机eeprom(代码片段)

        STC15系列单片机内部集成了大容量的EEPROM,与其程序空间是分开的。利用ISP/IAP技术可将内部DataFlash当EEPROM,擦写次数在10W次以上。EEPROM可分为若干个扇区,每个扇区包含512字节。使用时,建议同一次修... 查看详情