找回密码
 立即注册
查看: 56|回复: 7

STC8G2K32S2, ADC读取问题

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:1
  • 最近打卡:2026-03-16 12:07:51
已绑定手机

1

主题

4

回帖

13

积分

新手上路

积分
13
发表于 6 天前 | 显示全部楼层 |阅读模式
选用STC8G2K32S2 P1.3脚做ADC输入,P2.0-P2.4推挽输出,驱动对应的LED。 实现的功能是:根据P1.3脚ADC值的大小,点亮对应的LED, 程序实现不了,求指导

#include <STC8G.h>
#include <intrins.h>  // 包含_nop_()函数

// 系统时钟定义(烧录配置:24MHz)
#define FOSC 24000000L
#define ADC_MAX 4095   // STC8G2K32S2是12位ADC,最大值4095
#define ADCTIM  (*(unsigned char volatile xdata *)0xfea8)

// ADC控制位宏定义(STC8G原厂标准定义)
#define ADC_POWER   0x80    // ADC电源控制位(bit7)
#define ADC_START   0x08    // ADC启动控制位(bit3)
#define ADC_FLAG    0x10    // ADC完成标志位(bit4)

// LED引脚定义(P2.0=LED1,P2.4=LED2,低电平亮,上电灭)
sbit LED1 = P2^0;  
sbit LED2 = P2^4;

// 12位ADC阈值(基于你的实测电压换算)
#define A_ADC_MIN   1096    // 1146-50,容错范围
#define A_ADC_MAX   1196    // 1146+50
#define B_ADC_MIN   2368    // 2418-50
#define B_ADC_MAX   2468    // 2418+50

// 函数声明
void System_Init(void);
unsigned int ADC_Read(unsigned char ch);
void LED_Control(unsigned int adc_val);
void Delay_ms(unsigned int ms);

void main(void)
{
    unsigned int adc_value;  // C51要求变量在代码块开头定义
   
    // 系统初始化
    System_Init();
   
    while(1)
    {
        // 读取P1.3(ADC3)的12位ADC值
        adc_value = ADC_Read(3);  
        
        // 根据12位ADC值控制LED
        LED_Control(adc_value);
        
        // 24MHz下10ms防抖延时
        Delay_ms(10);
    }
}

/**
* @brief 系统初始化:LED推挽输出 + P1.3高阻输入 + 12位ADC配置
*/
void System_Init(void)
{
    // 1. LED引脚配置:推挽输出,上电高电平(灭)
    P2M0 |= (0x01 | 0x10);  // P2.0/P2.4推挽输出
    P2M1 &= ~(0x01 | 0x10);
    LED1 = 1;  
    LED2 = 1;  
   
    // 2. P1.3(ADC3)高阻输入(12位ADC采样最优模式)
    P1M0 &= ~0x08;  
    P1M1 |= 0x08;   
   
    // 3. 12位ADC初始化(STC8G2K32S2原厂配置)
    P_SW2 |= 0x80;          // 打开扩展寄存器
    ADCTIM = 0x3f;          // 最大采样时间,提升12位精度
    P_SW2 &= 0x7f;          // 关闭扩展寄存器
    ADCCFG = 0x07;          // 12位ADC模式 + Fosc/512(24MHz/512≈46.875KHz)
    ADC_RES = 0;            
    ADC_RESL = 0;
    ADC_CONTR = ADC_POWER;  // 开启ADC电源
    Delay_ms(1);            // 电源稳定
}

/**
* @brief 读取12位ADC值(STC8G2K32S2原生12位,直接读取完整值)
* @param ch: ADC通道(3=P1.3)
* @return 12位ADC值(0-4095)
*/
unsigned int ADC_Read(unsigned char ch)
{
    unsigned int adc_val;
    // 选择通道 + 启动转换
    ADC_CONTR = ADC_POWER | ch;  
    _nop_();_nop_();            
    ADC_CONTR |= ADC_START;     
    // 等待转换完成
    while (!(ADC_CONTR & ADC_FLAG));  
    ADC_CONTR &= ~ADC_FLAG;      
    // 读取12位结果:ADC_RES=高8位,ADC_RESL=低4位(12位核心!)
    adc_val = (unsigned int)ADC_RES << 4 | (ADC_RESL & 0x0F);
    return adc_val;
}

/**
* @brief 12位ADC值控制LED(A=1146→LED1亮,B=2418→LED2亮)
*/
void LED_Control(unsigned int adc_val)
{  
    // A信号(1.40V≈1146)→ LED1亮(低电平)
    if(adc_val >= A_ADC_MIN && adc_val <= A_ADC_MAX)
    {
        LED1 = 0;
        LED2 = 1;
    }
    // B信号(2.96V≈2418)→ LED2亮(低电平)
    else if(adc_val >= B_ADC_MIN && adc_val <= B_ADC_MAX)
    {
        LED1 = 1;
        LED2 = 0;
    }
    // 无信号→全灭
    else
    {
        LED1 = 1;
        LED2 = 1;
    }
}

/**
* @brief 24MHz适配的毫秒延时函数
*/
void Delay_ms(unsigned int ms)
{
    unsigned int i, j;
    for(i = ms; i > 0; i--)
        for(j = 240; j > 0; j--); // 24MHz下j=240≈1ms
}
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:1
  • 最近打卡:2026-03-16 12:07:51
已绑定手机

1

主题

4

回帖

13

积分

新手上路

积分
13
发表于 6 天前 | 显示全部楼层
这是图纸
截图202603161215272074.jpg
回复

使用道具 举报 送花

  • 打卡等级:常住居民II
  • 打卡总天数:82
  • 最近打卡:2026-03-20 20:44:49
已绑定手机

4

主题

222

回帖

818

积分

高级会员

积分
818
发表于 6 天前 | 显示全部楼层
调试方法:adc_value通过串口发送出来看看是多少。
电路看着有问题,ADC直接接到VCC吗?那能测啥
回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:196
  • 最近打卡:2026-03-22 00:01:11
已绑定手机

12

主题

217

回帖

1323

积分

金牌会员

DIY玩家

积分
1323
发表于 6 天前 | 显示全部楼层
lcws*** 发表于 2026-3-16 13:06
调试方法:adc_value通过串口发送出来看看是多少。
电路看着有问题,ADC直接接到VCC吗?那能测啥
...

可逐一功能验证
是否配置正确
真正的学徒往往怀着大师的心
回复

使用道具 举报 送花

  • 打卡等级:以坛为家III
  • 打卡总天数:644
  • 最近打卡:2026-03-20 08:58:57
已绑定手机

52

主题

2488

回帖

8796

积分

论坛元老

积分
8796
发表于 6 天前 | 显示全部楼层
参考附件例子,通过串口打印ADC采样结果,判断实际运行情况是否符合预期

16路ADC轮询-每路16次ADC转换取中间8次求平均值-串口1返回结果-STC8.zip

10.79 KB, 下载次数: 1

回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:1
  • 最近打卡:2026-03-16 12:07:51
已绑定手机

1

主题

4

回帖

13

积分

新手上路

积分
13
发表于 6 天前 | 显示全部楼层
lcws*** 发表于 2026-3-16 13:06
调试方法:adc_value通过串口发送出来看看是多少。
电路看着有问题,ADC直接接到VCC吗?那能测啥
...

接了个10K电阻,没画出来
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:1
  • 最近打卡:2026-03-16 12:07:51
已绑定手机

1

主题

4

回帖

13

积分

新手上路

积分
13
发表于 6 天前 | 显示全部楼层
乘风*** 发表于 2026-3-16 14:28
参考附件例子,通过串口打印ADC采样结果,判断实际运行情况是否符合预期

该芯片为10位ADC,是启动位错误,
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:1
  • 最近打卡:2026-03-16 12:07:51
已绑定手机

1

主题

4

回帖

13

积分

新手上路

积分
13
发表于 6 天前 | 显示全部楼层
仔细看了8G芯片手册,把启动位改为0X40,才行#include <STC8G.H>
#include <intrins.h>

// ==================== 全局变量(C51必须放最开头) ====================
unsigned int timer_value; // 蜂鸣器定时器重载值

// ==================== 宏定义+引脚定义 ====================
#define ADC_POWER   0x80
#define ADC_START   0x40
#define ADC_FLAG    0x20
#define P1ASF_REG   (*(unsigned char volatile *)0x9D)
sbit LED1 = P2^0;
sbit LED2 = P2^4;
#define A_MIN 250
#define A_MAX 320
#define B_MIN 580
#define B_MAX 630

// ==================== 【1】基础延时函数(最先定义,无依赖) ====================
void Delay1ms(void)
{
    unsigned char i, j;
    i = 32;
    j = 40;
    do { while(--j); } while(--i);
}

void DelayMs(unsigned int ms)
{
    while(ms--) Delay1ms();
}

// ==================== 【2】蜂鸣器核心函数(直接定义,无原型声明) ====================
void Buzzer_System_Init(void)
{
    // 时钟配置
    P_SW2 |= 0x80;   
    CLKDIV = 0x00;   
    P_SW2 &= ~0x80;
   
    // P5.4推挽输出+高驱动(最大化音量)
    P5M1 &= ~0x10;   
    P5M0 |= 0x10;
    P_SW2 |= 0x80;
    P5DR = 0x10;      // 高驱动模式,音量翻倍
    P_SW2 &= ~0x80;
   
    // 定时器0初始化
    TMOD &= 0xF0;     
    TMOD |= 0x01;     
    AUXR &= ~0x80;   
    ET0 = 1;         
    EA = 1;           
}

unsigned int Buzzer_Get_Timer_Value(unsigned int freq)
{
    if(freq == 0) return 0;
    // 2KHz时:timer_value = 65536 - (24000000/(12*2000*2)) = 65036
    return (65536UL - (24000000UL / (12UL * freq * 2)));
}

void Buzzer_Play_Tone(unsigned int freq, unsigned int duration_ms)
{
    unsigned char j;
    if(freq == 0)
    {
        TR0 = 0;   
        DelayMs(duration_ms);
        return;
    }
   
    timer_value = Buzzer_Get_Timer_Value(freq);
    TR0 = 0;                    
    TH0 = timer_value >> 8;     
    TL0 = timer_value & 0xFF;   
    TR0 = 1;                     // 启动定时器,生成2KHz方波
   
    DelayMs(duration_ms);
   
    // 渐弱停止(避免杂音,保留)
    TR0 = 0;
    for(j=0; j<3; j++)
    {
        P54 = !P54;
        DelayMs(20);
    }
}

// 定时器0中断服务函数(必须放在调用前)
void Timer0_ISR(void) interrupt 1
{
    TF0 = 0;         
    P54 = !P54;      
    TH0 = timer_value >> 8;     
    TL0 = timer_value & 0xFF;   
}

// ==================== 【3】ADC函数(直接定义) ====================
void ADC_Init(void)
{
    P1M0 = 0x00; P1M1 = 0xFF;
    P1ASF_REG = 0xFF;
    ADCCFG = 0x00;
    ADC_CONTR = ADC_POWER;
    DelayMs(5);
}

unsigned int Read_ADC(void)
{
    unsigned int adc_val = 0;
    unsigned char retry;
    for(retry=0; retry<5; retry++)
    {
        ADC_CONTR = ADC_POWER | 3;
        _nop_();_nop_();
        ADC_CONTR |= ADC_START;
        while(!(ADC_CONTR & ADC_FLAG));
        ADC_CONTR &= ~ADC_FLAG;
        adc_val += (ADC_RES<<2)|(ADC_RESL&0x03);
        DelayMs(1);
    }
    return adc_val / 5;
}

// ==================== 【4】主函数(最后定义) ====================
void main(void)
{
    unsigned int adc_val;
    unsigned char last_state = 0;
   
    // 初始化
    Buzzer_System_Init();
    ADC_Init();
    P2M0 |= 0x11; P2M1 &= ~0x11;
    LED1 = 1; LED2 = 1;
   
    // ==================== 新增:上电2秒提示音 ====================
    Buzzer_Play_Tone(2000, 800); // 2KHz洪亮提示音,持续2秒
    DelayMs(500); // 提示音结束后停顿0.5秒,再进入主循环
   
    while(1)
    {
        adc_val = Read_ADC();
        
        // A信号:2KHz洪亮提示音(150ms)
        if(adc_val >= A_MIN && adc_val <= A_MAX)
        {
            LED1 = 0; LED2 = 1;
            if(last_state != 1)
            {
                Buzzer_Play_Tone(2000, 150); // 2KHz洪亮提示音
                last_state = 1;
            }
        }
        // B信号:2KHz洪亮提示音(两声)
        else if(adc_val >= B_MIN && adc_val <= B_MAX)
        {
            LED1 = 1; LED2 = 0;
            if(last_state != 2)
            {
                Buzzer_Play_Tone(2000, 150);
                DelayMs(80);
                Buzzer_Play_Tone(2000, 150);
                last_state = 2;
            }
        }
        // 无信号
        else
        {
            LED1 = 1; LED2 = 1;
            last_state = 0;
        }
        
        DelayMs(10);
    }
}
回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-3-22 03:28 , Processed in 0.116875 second(s), 77 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表