STC8G1K08 ADC读取问题
选用STC8G1K08 P1.5脚做ADC输入,P3.4-P3.7、P1.0-P1.3推挽输出,驱动对应的LED。 实现的功能是:根据P1.5脚ADC值的大小,点亮对应的LED, 程序实现不了,求指导#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--);
} STC8G1K08没有ADC ?STC8G1K08A才有? 合适一下单片机是否带ADC,另外main函数第一句加上:
P_SW2 |= 0x80;
试试 原来设计的用DIP20 STCW15408AS,看DIP20 STC8G1K08便宜,结果后者无ADC 贵有贵的道理{:4_165:} 设计的用STC15W408AS DIP20,就用它了
STC8G1K08-16/20PIN的芯片有ADC
STC8G1K08-8PIN的没有ADC,STC8G1K08A-8PIN的也有ADC。
cjtdz 发表于 2026-3-3 12:16
#include
// 系统时钟定义12MHz
ADC_Read函数中启动位错误,ADC_CONTR = 0x80 | 0x40 | ch ;,另外STC8G1K08是10位ADC。 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