这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界» 论坛首页» 嵌入式开发» MCU» STC8G1K08A单片机中模数转换器ADC的应用问题

共7条 1/1 1 跳转至

STC8G1K08A单片机中模数转换器ADC的应用问题

工程师
2021-07-04 22:26:14 打赏

四个电阻串联,用STC8G1K08A单片机的P3^0口做模数转换ADC,用万用表测 2 3 4 点的电压,分别为 1.25V,2.50V,3.75V 按照理论,这三个点的模数变换数值应该为 256, 512, 768 ,实际显示的是250,377,440,除去变换的误差,这和理论值差的也太多了,程序是按照厂家提供的例程编写的,电路上的5V电压直接取自单片机的VCC和GND.测量时就是直接用杜邦线连P3^0口和 2 3 4 点,没有串限流电阻,也没有并分流电阻,这是程序出了问题还是电路出了问题?

求论坛里的大神给指点一二!


image.png




关键词: STC8G1K08A 模数转换器 ADC A/D

工程师
2021-07-04 23:13:24 打赏
2楼

给你一个应用实例参考,因电池供电,P3.2既作ADC输入,也作中断唤醒。ADC检测压力传感器信号,当无压力达到一定时间,进入休眠。一旦有压力MCU唤醒正常工作。你的问题可能是ADC转换结果寄存器设置不当。

//STC8G1K08A工作电压范围1.9~5.5V

//#include "reg51.h"

#include

#include "intrins.h"

typedef unsigned char uchar;

typedef unsigned int uint;

typedef unsigned long ulong;

#define ADCTIM (*(unsigned char volatile xdata *)0xfea8)

//#define ceiling 636 //上限

//#define floor 923 //下限

sbit LED_R=P5^4;

sbit LED_G=P5^5;

//sbit AVDD =P3^3;


uint code table[36]={

923 ,// 0

915 ,// 1

907 ,// 2

898 ,// 3

890 ,// 4

882 ,// 5

874 ,// 6

866 ,// 7

858 ,// 8

850 ,// 9

841 ,// 10

833 ,// 11

825 ,// 12

817 ,// 13

809 ,// 14

800 ,// 15

792 ,// 16

784 ,// 17

776 ,// 18

768 ,// 19

760 ,// 20

751 ,// 21

743 ,// 22

735 ,// 23

727 ,// 24

719 ,// 25

710 ,// 26

702 ,// 27

694 ,// 28

686 ,// 29

677 ,// 30

669 ,// 31

661 ,// 32

653 ,// 33

645 ,// 34

636 };//35


bit flag=0;//完成标志

//uchar i;

uint CY_ADC;//采样值

uint time;


void Timer0Init() //2毫秒@11.0592MHz

{

AUXR |= 0x80; //定时器时钟1T模式

TMOD &= 0xF0; //设置定时器自动重装模式

TL0 = 0x9A; //设置定时初值

TH0 = 0xA9; //设置定时初值

TF0 = 0; //清除TF0标志

TR0 = 1; //定时器0开始计时

}

/*----------------------------

读取ADC结果

----------------------------*/

void GetADCResult()

{ //ADC 控制器 电源 启动 完成 -- 15通道模拟选择位

//ADC_CONTR B7 B6 B5 B4 B3 B2 B1 B0

static uint count=0;

static uint PJZ_ADC=0; //累加10次采样的变量1


count++;

if(count==1)ADC_CONTR = 0x80; //使能ADC模块

if(count>=2&&count<=11)

{

ADC_CONTR|= 0x42; //启动AD转换,P3.2 ADC输入

_nop_();_nop_();

while (!(ADC_CONTR & 0x20)); //查询ADC完成标志

ADC_CONTR &= ~0x20; //清完成标志

PJZ_ADC+=(ADC_RES<<8|ADC_RESL); //累计10次读取10位ADC结果

}

if(count==11)

{

CY_ADC=PJZ_ADC/10;

PJZ_ADC=0;

ADC_CONTR = 0x00; //关闭ADC

flag=1;

}

if(count>=10)//200ms

count=0;

}


void main()

{

P3M0 = 0x00; //设置P3.2为ADC口

P3M1 = 0x04; //设置P3.2为ADC口

P5M0 = 0x00;

P5M1 = 0x00;

P_SW2 |= 0x80; //打开

ADCTIM = 0x3f; //设置 ADC 内部时序

P_SW2 &= 0x7f; //关闭

ADCCFG = 0x27; //设置ADC结果右对齐,速度为512系统时钟 ADCCFG = 0x0f; // 设置 ADC 时钟为系统时钟 /2/16/16

// ADC_CONTR = 0x80; // 使能 ADC 模块

Timer0Init();

//ADC配置寄存器 -- -- 格式控制 -- 速度控制位

// ADCCFG B7 B6 B5 B4 B3 B2 B1 B0

while (1)

{

if(TF0)

{

TF0=0;

GetADCResult();

if(flag==1)

{

flag=0;

if(CY_ADC>table[0])

{

time++;

LED_R=1;

LED_G=1;

}

else if(CY_ADC>table[0] && CY_ADC

{

time=0;

LED_R=1;

LED_G=0;

}

else if(CY_ADC

{

time=0;

LED_R=0;

LED_G=0;

}

if(time>=15000)

{

time=0;

P3M1 = 0x00;//设置P3.2为准双向

// AVDD = 0;

TR0 = 0;//关闭定时器

EX0 = 1; // 使能 INT0 中断 , 用于唤醒 MCU

EA = 1;

_nop_();_nop_();_nop_();_nop_();

PCON = IDL; //MCU 进入空闲(省电)模式

_nop_();_nop_();_nop_();_nop_();

}

}

}

}

}


void INT0_Isr() interrupt 0

{

EX0 = 0; // 关闭 INT0 中断

EA = 0; // 关闭总中断

// AVDD = 1;

P3M1=0x04; //设置P3.2为ADC口

TR0 = 1; //启动定时器

}




工程师
2021-07-04 23:17:13 打赏
3楼

楼主,你代码呢?
STC8G1K08A这个IC容易受干扰,特别是电路中有高频信号的情况下
在ADC的采样输入一定要有一个104以上的电容,而且得是靠近端口的
单片机的VCC一定在做好滤波,104电容一定要靠近VCC
GND不能到处乱跑


工程师
2021-07-04 23:21:39 打赏
4楼

用一个高精度的电压表对比一下


工程师
2021-07-05 22:22:59 打赏
5楼

官方好像有ADC例子吧? 套用看看


工程师
2021-07-05 22:26:45 打赏
6楼

确定硬件没连错?


工程师
2021-07-05 22:31:59 打赏
7楼

经验告诉我,多数情况下是用户自己的问题,如写错代码或操作错误等等


共7条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册]