STC32G单片机内置ADC及应用编程

STC32G单片机内置ADC及应用编程

一 STC32G单片机内置ADC模块简介

STC32G单片机内部集成了一个12位高速ADC转换器,ADC的最高时钟频率为系统频率的1/2。其输入通道多达15个(第15通道为专门测量内部1.19V参考信号源的通道),可分时切换使用。

STC15系列单片机内置ADC模块以电源电源作为ADC参考电压,STC32G的ADC模块则与之不同,它有单独的参考电压源引脚,可以接入精准的参考电压(0~5V皆可),以获得稳定的ADC值;参考电源引脚也可直接与MCU供电电源连接,不过AD转换结果可能会收到电源电源波动的影响。注意:STC32GADC模块的参考电压输入引脚不可悬空。

STC32G单片机的内置ADC模块转换结果存储在两个8位寄存器中,可配置为左对齐(高8位存储在高位寄存器ADC_RES中,低四位存储在低位寄存器ADC_REL的高四位中),可配置为右对齐(高4位存储在高位寄存器ADC_RES的低4位中,低8位存储在低位寄存器ADC_REL中)。

二 STC32G单片机内置ADC模块的相关寄存器

STC32G单片机内置ADC模块的相关寄存器包含控制寄存器ADC_CONTR、转换结果高位寄存器ADC_RES、转换结果低位寄存器ADC_RESL、配置寄存器ADCCFG、时序控制寄存器ADCTIM。下面是STC用户手册对这几个寄存器的功能介绍。

寄存器ADC_CONTR

配置寄存器ADCCFG

时序控制寄存器ADCTIM

三 ADC模块函数库编程

ADC模块应用离不开相关寄存器编程,先将常用的寄存器配置操作编写成库函数供以后调用。

头文件

/*STC32G_ADC.h

Designed by Bill Liu

Version 0.0

Modified last by Bill Liu,7/21/2022

/////////////////////////////enum//////////////////////

STC32G_ADC_CHN //STC32G ADC channel

STC32G_ADC_SPEED //STC32G ADC clock frequency

/////////////////////////////Macro function////////////

STC32G_ADCPOWERON(); //adc power on

STC32G_ADCPOWEROFF(); //adc power off

STC32G_ADCSTART(); //adc start

STC32G_ADCSTOP(); //adc stop

STC32G_ADCCLEARFLAG(): //clear flag

STC32G_ADCPWMTRIENBLE(); //PWM trigger adc enable

STC32G_ADCPWMTRIDISBLE(); //PWM trigger adc disable

STC32G_ADCSELCH0(); //selected ADC_CH0

STC32G_ADCSELCH1(); //selected ADC_CH1

STC32G_ADCSELCH2(); //selected ADC_CH2

STC32G_ADCSELCH3(); //selected ADC_CH3

STC32G_ADCSELCH4(); //selected ADC_CH4

STC32G_ADCSELCH5(); //selected ADC_CH5

STC32G_ADCSELCH6(); //selected ADC_CH6

STC32G_ADCSELCH7(); //selected ADC_CH7

STC32G_ADCSELCH8(); //selected ADC_CH8

STC32G_ADCSELCH9(); //selected ADC_CH9

STC32G_ADCSELCH10(); //selected ADC_CH10

STC32G_ADCSELCH11(); //selected ADC_CH11

STC32G_ADCSELCH12(); //selected ADC_CH12

STC32G_ADCSELCH13(); //selected ADC_CH13

STC32G_ADCSELCH14(); //selected ADC_CH14

STC32G_ADCSELCH15(); //selected ADC_CH15 at inner band gap voltage

STC32G_ADCRESLALIG(); //adc result left alignment

STC32G_ADCRESRALIG(): //adc result right alignment

//////////////////fuanction/////////////////////////

STC32G_AdcSelChn(STC32G_ADC_CHN chn); //return void

STC32G_AdcSelSpeed(STC32G_ADC_SPEED selSpeed); //return void

STC32G_AdcStructInitDef(STC32G_ADC_TypeDef* pStruct); //return void

STC32G_AdcInit(STC32G_ADC_TypeDef mStruct); //return void

STC32G_AdcGetRes(ui16* pResult); //return ui16

*/

#ifndef __STC32G_ADC_H

#define __STC32G_ADC_H

#include "config.h"

#include "STC32G_GPIO.h"

#define STC32G_ADCPOWERON() {ADC_POWER = 1;} //adc power on

#define STC32G_ADCPOWEROFF() {ADC_POWER = 0;} //adc power off

#define STC32G_ADCSTART() {ADC_START = 1;} //adc start

#define STC32G_ADCSTOP() {ADC_START = 0;} //adc stop

#define STC32G_ADCCLEARFLAG() {ADC_FLAG = 0;} //clear flag

#define STC32G_ADCPWMTRIENBLe() {ADC_EPWMT = 1;} //PWM trigger adc enable

#define STC32G_ADCPWMTRIDISBLE() {ADC_EPWMT = 0;} //PWM trigger adc disable

#define STC32G_ADCSELCH0() {STC32G_P1MODE_HIIN(PIN0); ADC_CONTR &= 0xF0;} //selected ADC_CH0

#define STC32G_ADCSELCH1() {STC32G_P1MODE_HIIN(PIN1); ADC_CONTR &= 0xF0; ADC_CONTR |= 0x01;} //selected ADC_CH1

#define STC32G_ADCSELCH2() {STC32G_P1MODE_HIIN(PIN2); ADC_CONTR &= 0xF0; ADC_CONTR |= 0x02;} //selected ADC_CH2

#define STC32G_ADCSELCH3() {STC32G_P1MODE_HIIN(PIN3); ADC_CONTR &= 0xF0; ADC_CONTR |= 0x03;} //selected ADC_CH3

#define STC32G_ADCSELCH4() {STC32G_P1MODE_HIIN(PIN4); ADC_CONTR &= 0xF0; ADC_CONTR |= 0x04;} //selected ADC_CH4

#define STC32G_ADCSELCH5() {STC32G_P1MODE_HIIN(PIN5); ADC_CONTR &= 0xF0; ADC_CONTR |= 0x05;} //selected ADC_CH5

#define STC32G_ADCSELCH6() {STC32G_P1MODE_HIIN(PIN6); ADC_CONTR &= 0xF0; ADC_CONTR |= 0x06;} //selected ADC_CH6

#define STC32G_ADCSELCH7() {STC32G_P1MODE_HIIN(PIN7); ADC_CONTR &= 0xF0; ADC_CONTR |= 0x07;} //selected ADC_CH7

#define STC32G_ADCSELCH8() {STC32G_P0MODE_HIIN(PIN0); ADC_CONTR &= 0xF0; ADC_CONTR |= 0x08;} //selected ADC_CH8

#define STC32G_ADCSELCH9() {STC32G_P0MODE_HIIN(PIN1); ADC_CONTR &= 0xF0; ADC_CONTR |= 0x09;} //selected ADC_CH9

#define STC32G_ADCSELCH10() {STC32G_P0MODE_HIIN(PIN2); ADC_CONTR &= 0xF0; ADC_CONTR |= 0x10;} //selected ADC_CH10

#define STC32G_ADCSELCH11() {STC32G_P0MODE_HIIN(PIN3); ADC_CONTR &= 0xF0; ADC_CONTR |= 0x11;} //selected ADC_CH11

#define STC32G_ADCSELCH12() {STC32G_P0MODE_HIIN(PIN4); ADC_CONTR &= 0xF0; ADC_CONTR |= 0x12;} //selected ADC_CH12

#define STC32G_ADCSELCH13() {STC32G_P0MODE_HIIN(PIN5); ADC_CONTR &= 0xF0; ADC_CONTR |= 0x13;} //selected ADC_CH13

#define STC32G_ADCSELCH14() {STC32G_P0MODE_HIIN(PIN6); ADC_CONTR &= 0xF0; ADC_CONTR |= 0x14;} //selected ADC_CH14

#define STC32G_ADCSELCH15() { ADC_CONTR &= 0xF0; ADC_CONTR |= 0x15;} //selected band gap voltage

#define STC32G_ADCRESLALIG() {RESFMT = 0;} //adc result left alignment

#define STC32G_ADCRESRALIG() {RESFMT = 1;} //adc result right alignment

//******************************************************

typedef enum

{

ADC_CH0 = 0, //ADC channel 0 at P10

ADC_CH1, //ADC channel 1 at P11

ADC_CH2, //ADC channel 2 at P54

ADC_CH3, //ADC channel 3 at P13

ADC_CH4, //ADC channel 4 at P14

ADC_CH5, //ADC channel 5 at P15

ADC_CH6, //ADC channel 6 at P16

ADC_CH7, //ADC channel 7 at P17

ADC_CH8, //ADC channel 8 at P00

ADC_CH9, //ADC channel 9 at P01

ADC_CH10, //ADC channel 10 at P02

ADC_CH11, //ADC channel 11 at P03

ADC_CH12, //ADC channel 12 at P04

ADC_CH13, //ADC channel 13 at P05

ADC_CH14, //ADC channel 14 at P06

ADC_CH15, //ADC channel 15 at inner band gap voltage

}STC32G_ADC_CHN; //STC32G ADC channel

//******************************************************

typedef enum

{

FOSC_DIV_2X1 = 0, // FOSC / (2 * 1)

FOSC_DIV_2X2, // FOSC / (2 * 2)

FOSC_DIV_2X3, // FOSC / (2 * 3)

FOSC_DIV_2X4, // FOSC / (2 * 4)

FOSC_DIV_2X5, // FOSC / (2 * 5)

FOSC_DIV_2X6, // FOSC / (2 * 6)

FOSC_DIV_2X7, // FOSC / (2 * 7)

FOSC_DIV_2X8, // FOSC / (2 * 8)

FOSC_DIV_2X9, // FOSC / (2 * 9)

FOSC_DIV_2X10, // FOSC / (2 * 10)

FOSC_DIV_2X11, // FOSC / (2 * 11)

FOSC_DIV_2X12, // FOSC / (2 * 12)

FOSC_DIV_2X13, // FOSC / (2 * 13)

FOSC_DIV_2X14, // FOSC / (2 * 14)

FOSC_DIV_2X15, // FOSC / (2 * 15)

FOSC_DIV_2X16, // FOSC / (2 * 16)

}STC32G_ADC_SPEED; //STC32G ADC clock frequency

//******************************************************

typedef struct

{

BOOL adcPowerOn; //ADC power on enable/disable, 0-disable, 1-enable

STC32G_ADC_CHN adcChn; //slected adc channel

BOOL pwmTrigAble;

STC32G_ADC_SPEED adcSpeed; //STC32G_ADC_SPEED

BOOL adcResultRA; //adc result_data style,0:left alignment(default), 1:right alignment

BOOL adcSetupTime; //ADC channel select setup time control congigure, 0: 1 system clock cycles(default), 1: 2 system clock cycles

u8 adcHoldTime; //ADC channel select hold time control congigure. 0: 1 ADC clock cycle time, 1:2 ADC clock cycle times

u8 adcSampleTime; //analog signal sampling control time. 10 min. recommended 0x1F

}STC32G_ADC_TypeDef;

/******************************************************

Function: STC32G_AdcSelChn(STC32G_ADC_CHN chn);

return value: void

chn:adc channel

description: select adc channel

Example:

STC32G_AdcSelChn(ADC_CH0);

******************************************************/

void STC32G_AdcSelChn(STC32G_ADC_CHN chn);

/******************************************************

Function: STC32G_AdcSelSpeed(STC32G_ADC_SPEED selSpeed);

return value: void

selSpeed:selected speed

description: configure adc speed

Example:

STC32G_AdcSelSpeed(FOSC_DIV_2X16);

******************************************************/

void STC32G_AdcSelSpeed(STC32G_ADC_SPEED selSpeed);

/******************************************************

Function: STC32G_AdcInitDef(STC32G_ADC_TypeDef* pStruct);

return value: void

pStruct: STC32G_ADC_TypeDef struct address to be inited to default

description: Init STC32G_ADC_TypeDef struct to default value

Example:

STC32G_ADC_TypeDef mStruct;

STC32G_AdcInitDef(&mStruct);

******************************************************/

void STC32G_AdcInitDef(STC32G_ADC_TypeDef* pStruct);

/******************************************************

Function: STC32G_AdcInit(STC32G_ADC_TypeDef mStruct);

return value: void

mStruct: configure STC32G by mStruct

description: init adc

Example:

STC32G_ADC_TypeDef mStruct;

STC32G_AdcInit(mStruct);

******************************************************/

void STC32G_AdcInit(STC32G_ADC_TypeDef mStruct);

/******************************************************

Function: STC32G_AdcGetRes(ui16* pResult);

return value: ui16

pResult: address to store got result

description: get adc result

Example:

ui16 mReult;

STC32G_AdcGetRes(&mReult);

******************************************************/

u16 STC32G_AdcGetRes(ui16* pResult);

#endif

源文件

/*STC32G_ADC.c

Designed by Bill Liu

Version 0.0

Modified last by Bill Liu, 07/21/2022

*/

#include "STC32G_ADC.h"

//******************************************************

void STC32G_AdcSelChn(STC32G_ADC_CHN chn)

{

switch(chn)

{

case ADC_CH0:

STC32G_ADCSELCH0()

break;

case ADC_CH1:

STC32G_ADCSELCH1()

break;

case ADC_CH2:

STC32G_ADCSELCH2()

break;

case ADC_CH3:

STC32G_ADCSELCH3()

break;

case ADC_CH4:

STC32G_ADCSELCH4()

break;

case ADC_CH5:

STC32G_ADCSELCH5()

break;

case ADC_CH6:

STC32G_ADCSELCH6()

break;

case ADC_CH7:

STC32G_ADCSELCH7()

break;

case ADC_CH8:

STC32G_ADCSELCH8()

break;

case ADC_CH9:

STC32G_ADCSELCH9()

break;

case ADC_CH10:

STC32G_ADCSELCH10()

break;

case ADC_CH11:

STC32G_ADCSELCH11()

break;

case ADC_CH12:

STC32G_ADCSELCH12()

break;

case ADC_CH13:

STC32G_ADCSELCH13()

break;

case ADC_CH14:

STC32G_ADCSELCH14()

break;

case ADC_CH15:

STC32G_ADCSELCH15()

break;

}

}

//End of STC32G_AdcSelChn(STC32G_ADC_CHN chn)

//******************************************************

void STC32G_AdcSelSpeed(STC32G_ADC_SPEED selSpeed)

{

ADCCFG &= 0xF0;

ADCCFG |= selSpeed;

}

//End of STC32G_AdcSelSpeed(STC32G_ADC_SPEED selSpeed)

//******************************************************

void STC32G_AdcInitDef(STC32G_ADC_TypeDef* pStruct)

{

pStruct -> adcPowerOn = 0;

pStruct -> adcChn = ADC_CH0;

pStruct -> pwmTrigAble = 0; //PWM trigger disable

pStruct -> adcSpeed = FOSC_DIV_2X1; //adc clk is sclok/2

pStruct -> adcResultRA = 0; //adc result left align

pStruct -> adcSetupTime = 0; //Tadcsetup a adc clk

pStruct -> adcHoldTime = 0x01; //adc hold time 2 adc clk

pStruct -> adcSampleTime = 0x0A; //adc sampling time: 11 adc clk, 0x0A <= adcSampleTime <= 0x1F

}

//End of STC32G_AdcInitDef(STC32G_ADC_TypeDef* pStruct)

//******************************************************

void STC32G_AdcInit(STC32G_ADC_TypeDef mStruct)

{

STC32G_AdcSelChn(mStruct.adcChn);

ADC_EPWMT = mStruct.pwmTrigAble;

ADCCFG &= 0xF0;

ADCCFG |= mStruct.adcSpeed;

RESFMT = mStruct.adcResultRA;

ADCTIM &= 0x7F;

ADCTIM |= mStruct.adcSetupTime;

ADCTIM &= 0x9F;

ADCTIM |= mStruct. adcHoldTime;

ADCTIM &= 0xE0;

ADCTIM |= mStruct. adcSampleTime;

ADC_POWER = mStruct.adcPowerOn;

}

//End of STC32G_AdcInit(STC32G_ADC_TypeDef mStruct)

//******************************************************

u16 STC32G_AdcGetRes(ui16* pResult)

{

*pResult = 0;

STC32G_ADCSTART();

_nop_();

_nop_();

while(!ADC_FLAG);

STC32G_ADCCLEARFLAG()

*pResult = ADC_RES;

if(RESFMT)

{

*pResult <<= 8;

*pResult += ADC_RESL;

}

else

{

*pResult <<= 4;

*pResult += ADC_RESL >> 4;

}

return *pResult;

}

//End of STC32G_AdcGetRes(ui16* pResult)

四 应用编程示例

下面写段示例程序,演示ADC库文件的使用。

头文件:

/*main.h

Designed by Bill Liu

Version 0.0

Modified last by Bill Liu ,04/18/2023

*/

#ifndef __MAIN_H__

#define __MAIN_H__

//#include "myport.h"

#include "mtype.h"

#include "config.h"

#include "STC32G_GPIO.h"

#include "STC32G_Delay.h"

#include "STC32G_UART.h"

//#include "STC32G_EEPROM.h"

//#include "STC32G_PWM.h"

#include "STC32G_ADC.h"

//#include "STC32G_EEPROM.H"

//#include "STC32G_SPI.h"

//#include "STC32G_PWM.h"

//#include "STC32G_Timer.h"

//#include "STC32G_comparator.h"

STC32G_ADC_TypeDef mstruct;

#endif

源文件:

/*main.c

Designed by Bill Liu

Version 0.0

Modified last by Bill Liu, 03/25/2023

*/

#include "main.h"

ui8 str[30] = {0};

ui16 ADCRes = 0;

f32 TestVoltage = 0;

void main()

{

SysInit();

Uart1_Init(VBAUD_8BITS,G1, 0, 9600);

STC32G_AdcInitDef(&mstruct);

mstruct.adcPowerOn = 1;

mstruct.adcChn = ADC_CH0;

mstruct.pwmTrigAble = 0;

mstruct.adcSpeed = FOSC_DIV_2X16;

mstruct.adcHoldTime = 0x01;

mstruct.adcSampleTime = 0x1F;

STC32G_AdcInit(mstruct);

while(1)

{

STC32G_AdcGetRes(&ADCRes);

Uart1_SendString("ADCRes = ");

LongToString(ADCRes,str);

Uart1_SendString(str);

Uart1_SendString("\r\n");

TestVoltage = 5000.0/4096*ADCRes;

FloatString(TestVoltage,str,2);

Uart1_SendString("TestVoltage = ");

Uart1_SendString(str);

Uart1_SendString("mV");

Uart1_SendString("\r\n");

/*

STC32G_ADCSELCH15()

STC32G_AdcGetRes(&ADCRes);

Uart1_SendString("ADCRes = ");

LongToString(ADCRes,str);

Uart1_SendString(str);

Uart1_SendString("\r\n");

TestVoltage = 5000.0/4096*ADCRes;

FloatString(TestVoltage,str,2);

Uart1_SendString("Inner Bandgap Voltage = ");

Uart1_SendString(str);

Uart1_SendString("mV");

Uart1_SendString("\r\n");

STC32G_ADCSELCH0()

*/

Uart1_SendString("This a ADC Test Program!");

Uart1_SendString("\r\n");

Uart1_SendString("\r\n");

Uart1_SendString("\r\n");

Delayxms(1000);

}

}

//End of main()

测试板的参考电压为基准电压芯片AD586提供的5V电压。下面用一个10K的电位器将5V电源电压分压,将分压接到P1.0做AD输入,用ADC来测试分得电压的大小。

测得基准电压值:

测得分压值:

将程序编译,下载到单片机,在串口助手上看到的结果如下:

将源文件中的注释去掉,再获取内部Bandgap的ADC值,并将其转换为电压,结果如下:

从结果可以看出,获得的Bandgap电压并不是手册上所说的1.19V,至于为什么,不是此处讨论的范围。本例已完整演示了,如何调用ADC库函数,实现ADC值获取及如何用ADC测量电压。

相关库函数及示例源代码下载链接:

https://download.csdn.net/download/billliu66/87701680