cjtdz 发表于 2026-3-3 12:14:48

STC8G1K08 ADC读取问题

选用STC8G1K08 P1.5脚做ADC输入,P3.4-P3.7、P1.0-P1.3推挽输出,驱动对应的LED。 实现的功能是:根据P1.5脚ADC值的大小,点亮对应的LED, 程序实现不了,求指导

cjtdz 发表于 2026-3-3 12:16:12

#include <STC8G.h>

// 系统时钟定义12MHz
#define FOSC 12000000L
#define ADC_MAX 4095// 12位ADC最大值

// LED引脚定义(共7个,高电平点亮)
sbit LED1 = P3^4;// 最低ADC值对应点亮
sbit LED2 = P3^5;
sbit LED3 = P3^6;
sbit LED4 = P3^7;
sbit LED5 = P1^0;
sbit LED6 = P1^1;
sbit LED7 = P1^2;// 最高ADC值对应点亮

// 函数声明
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;
   
    // 系统初始化(推挽输出+ADC配置)
    System_Init();
   
    while(1)
    {
      // 读取P1.5的ADC值(12位精度)
      adc_value = ADC_Read(5);// 5对应P1.5通道
      
      // 根据ADC值阶梯点亮LED(高电平点亮)
      LED_Control(adc_value);
      
      // 延时稳定显示,避免闪烁
      Delay_ms(100);
    }
}

/**
* @brief 系统初始化:LED引脚配置为推挽输出,ADC初始化
* 适配12MHz时钟,移除P1ASF,兼容STC8G1K08
*/
void System_Init(void)
{
    // 1. 配置LED引脚为推挽输出(关键:P1M0/P3M0置1,P1M1/P3M1置0)
    // P1.0-P1.2推挽输出
    P1M0 |= 0x07;// P1M0对应位=1:推挽/强推挽
    P1M1 &= ~0x07; // P1M1对应位=0:推挽输出模式
    // P3.4-P3.7推挽输出
    P3M0 |= 0xF0;// P3.4-P3.7对应位(bit4-bit7)置1
    P3M1 &= ~0xF0; // P3.4-P3.7对应位清0
   
    // 初始状态:所有LED熄灭(低电平)
    LED1 = 0;
    LED2 = 0;
    LED3 = 0;
    LED4 = 0;
    LED5 = 0;
    LED6 = 0;
    LED7 = 0;
   
    // 2. ADC初始化(适配STC8G1K08,12MHz时钟下无需额外调整)
    ADC_CONTR = 0x80;// 开启ADC电源(ADON=1)
    ADC_RES = 0;       // 清空ADC结果寄存器
    ADC_RESL = 0;
    Delay_ms(1);       // ADC电源稳定延时(必须)
}

/**
* @brief 读取指定通道的ADC值(12位精度,适配12MHz时钟)
* @param ch: ADC通道(0-7对应P1.0-P1.7)
* @return 12位ADC值(0-4095)
*/
unsigned int ADC_Read(unsigned char ch)
{
    unsigned int adc_result;
   
    // 设置ADC通道,启动转换(0x80=开启ADC,0x08=启动转换)
    ADC_CONTR = 0x80 | (ch & 0x07) | 0x08;
   
    // 等待转换完成(ADC_FLAG位(bit4)为1表示完成)
    while(!(ADC_CONTR & 0x10));
   
    // 拼接12位结果:ADC_RES(高8位) + ADC_RESL(低4位)
    adc_result = (unsigned int)ADC_RES << 4;
    adc_result |= (ADC_RESL & 0x0F);
   
    // 清除转换完成标志,准备下一次转换
    ADC_CONTR &= ~0x10;
   
    return adc_result;
}

/**
* @brief 根据ADC值阶梯点亮LED(高电平点亮)
* @param adc_val: ADC采集值(0-4095)
*/
void LED_Control(unsigned int adc_val)
{
    // 先熄灭所有LED(置低电平)
    LED1 = 0;
    LED2 = 0;
    LED3 = 0;
    LED4 = 0;
    LED5 = 0;
    LED6 = 0;
    LED7 = 0;
   
    // 阶梯点亮逻辑(阈值可根据实际需求调整)
    if(adc_val > 585)LED1 = 1;// 第1级:ADC>585,LED1高电平点亮
    if(adc_val > 1170) LED2 = 1;// 第2级:ADC>1170,LED2点亮
    if(adc_val > 1755) LED3 = 1;// 第3级:ADC>1755,LED3点亮
    if(adc_val > 2340) LED4 = 1;// 第4级:ADC>2340,LED4点亮
    if(adc_val > 2925) LED5 = 1;// 第5级:ADC>2925,LED5点亮
    if(adc_val > 3510) LED6 = 1;// 第6级:ADC>3510,LED6点亮
    if(adc_val > 4000) LED7 = 1;// 第7级:ADC接近最大值,LED7点亮
}

/**
* @brief 毫秒级延时函数(核心修改:适配12MHz时钟)
* @param ms: 延时毫秒数,12MHz下该函数延时精度约±1ms
*/
void Delay_ms(unsigned int ms)
{
    unsigned int i, j;
    // 12MHz时钟下,内层循环次数调整为1000(保证1ms延时)
    for(i = ms; i > 0; i--)
      for(j = 1000; j > 0; j--);
}

wjhhhhh 发表于 2026-3-3 12:36:30

STC8G1K08没有ADC ?STC8G1K08A才有?

晓飛飛 发表于 2026-3-3 13:06:04

合适一下单片机是否带ADC,另外main函数第一句加上:
P_SW2 |= 0x80;
试试

cjtdz 发表于 2026-3-3 13:23:39

原来设计的用DIP20 STCW15408AS,看DIP20 STC8G1K08便宜,结果后者无ADC

_奶咖君_ 发表于 2026-3-3 13:31:53

贵有贵的道理{:4_165:}

cjtdz 发表于 2026-3-3 13:36:22

设计的用STC15W408AS DIP20,就用它了

乘风飞扬 发表于 2026-3-3 14:02:22

STC8G1K08-16/20PIN的芯片有ADC




STC8G1K08-8PIN的没有ADC,STC8G1K08A-8PIN的也有ADC。

wulin 发表于 2026-3-3 15:09:38

cjtdz 发表于 2026-3-3 12:16
#include

// 系统时钟定义12MHz


ADC_Read函数中启动位错误,ADC_CONTR = 0x80 | 0x40 | ch ;,另外STC8G1K08是10位ADC。

wulin 发表于 2026-3-3 15:45:13

cjtdz 发表于 2026-3-3 12:16
#include

// 系统时钟定义12MHz


#include <STC8G.h>

// 系统时钟定义12MHz
#define FOSC 12000000L
#define ADC_MAX 4095// 12位ADC最大值
#define ADCTIM(*(unsigned char volatile xdata *)0xfea8)
#define ADC_POWER   0x80                        //ADC power control dit (宏定义ADC电源控制位)1000 0000
#define ADC_START   0x40                        //ADC start control dit (宏定义ADC启动控制位)0100 0000
#define ADC_FLAG    0x20                        //ADC complete flag (宏定义ADC完成标志位)    0010 0000
#define ADC_EPWMT   0x10                        //使能 PWM实时触发 ADC                     0001 0000
// LED引脚定义(共7个,高电平点亮)
sbit LED1 = P3^4;// 最低ADC值对应点亮
sbit LED2 = P3^5;
sbit LED3 = P3^6;
sbit LED4 = P3^7;
sbit LED5 = P1^0;
sbit LED6 = P1^1;
sbit LED7 = P1^2;// 最高ADC值对应点亮

// 函数声明
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;
   
    // 系统初始化(推挽输出+ADC配置)
    System_Init();
   
    while(1)
    {
      // 读取P1.5的ADC值(10位精度)
      adc_value = ADC_Read(5);// 5对应P1.5通道
      
      // 根据ADC值阶梯点亮LED(高电平点亮)
      LED_Control(adc_value);
      
      // 延时稳定显示,避免闪烁
      Delay_ms(100);
    }
}

/**
* @brief 系统初始化:LED引脚配置为推挽输出,ADC初始化
* 适配12MHz时钟,移除P1ASF,兼容STC8G1K08
*/
void System_Init(void)
{
    P1M0 = 0x07; P1M1 = 0x20;// P1.0~1.2推挽,P1.5高阻,其余准双向
    P3M0 = 0xf0; P3M1 = 0x00;// P3.4~3.7推挽,其余准双向
    P5M0 = 0xf0; P5M1 = 0x00;// 准双向

    // 初始状态:所有LED熄灭(低电平)
    LED1 = 0;
    LED2 = 0;
    LED3 = 0;
    LED4 = 0;
    LED5 = 0;
    LED6 = 0;
    LED7 = 0;
   
    // 2. ADC初始化(适配STC8G1K08,12MHz时钟下无需额外调整)
        P_SW2 |= 0x80;                        //打开
        ADCTIM = 0x3f;                        //设置 ADC 内部时序
        P_SW2 &= 0x7f;                        //关闭
        ADCCFG = 0x27;                        //设置ADC结果右对齐,速度为512系统时钟
        ADC_RES=0;                                //清除ADC_RES存储器以前的结果
        ADC_RESL=0;
        ADC_CONTR=ADC_POWER;         //ADC 开启电源
        Delay_ms(1);            // ADC电源稳定延时(必须)
}

/**
* @brief 读取指定通道的ADC值(10位精度,适配12MHz时钟)
* @param ch: ADC通道(0-7对应P1.0-P1.7)
* @return 10位ADC值(0-1023)
*/
unsigned int ADC_Read(unsigned char ch)
{
        ADC_CONTR=ADC_POWER|ADC_START|ch;//启动转换1100 1000
        _nop_();_nop_();                                //小延时
        while (!(ADC_CONTR & ADC_FLAG));//等待ADC转换完成标志置位 1010 0000
        ADC_CONTR &=~ADC_FLAG;                        //清完成标志
        return ADC_RES<<8|ADC_RESL;                //返回十位ADC结果
}

/**
* @brief 根据ADC值阶梯点亮LED(高电平点亮)
* @param adc_val: ADC采集值(0-4095)
*/
void LED_Control(unsigned int adc_val)
{
    // 阶梯点亮逻辑(阈值可根据实际需求调整)
    if(adc_val > ( 585/4)) LED1 = 1; else LED1 = 0; // 第1级:ADC>585,LED1高电平点亮
    if(adc_val > (1170/4)) LED2 = 1; else LED2 = 0; // 第2级:ADC>1170,LED2点亮
    if(adc_val > (1755/4)) LED3 = 1; else LED3 = 0; // 第3级:ADC>1755,LED3点亮
    if(adc_val > (2340/4)) LED4 = 1; else LED4 = 0; // 第4级:ADC>2340,LED4点亮
    if(adc_val > (2925/4)) LED5 = 1; else LED5 = 0; // 第5级:ADC>2925,LED5点亮
    if(adc_val > (3510/4)) LED6 = 1; else LED6 = 0; // 第6级:ADC>3510,LED6点亮
    if(adc_val > (4000/4)) LED7 = 1; else LED7 = 0; // 第7级:ADC接近最大值,LED7点亮
}

/**
* @brief 毫秒级延时函数(核心修改:适配12MHz时钟)
* @param ms: 延时毫秒数,12MHz下该函数延时精度约±1ms
*/
void Delay_ms(unsigned int ms)
{
    unsigned int i, j;
    // 12MHz时钟下,内层循环次数调整为1000(保证1ms延时)
    for(i = ms; i > 0; i--)
      for(j = 1000; j > 0; j--);
}

页: [1] 2
查看完整版本: STC8G1K08 ADC读取问题