想通过adc采集电压,让一个引脚接6个按键进行不同的功能,经过计算后接入不同的电阻如原理图,但是s1和s2处实际电压跟算出来的不一样,后面我把单片机1脚的电路断开,单独测了1脚的电压有2.8v,s1和s2的电压也跟计算的一样了。有什么办法能够让1脚的电压不影响到s1和2呀,还是只能重新计算阻值了,但是那个实际的电压我也想不通是怎么算出来的,有没有大神救救我理论电压:s1:0.41v s2:1.24v s3:2.07v s4:2.91v s5:3.73v s6:4.57v
实际电压:s1:1.89v s2:1.89v s3:2.23v s4:2.94v s5:3.5v s6:4.6v
按键电压范围:s1:0-0.83v s2:0.83-1.66v s3:1.66-2.49v s4:2.49-3.32v s5:3.32-4.15v s6:4.15-4.9v
还有一个就是我s3 s4 s5 s6的电压跟计算的差不多,但是按键的功能也实现不了,调光程序是之前写好的可以用的,我就在里面加了adc和check_keys函数,不知道为什么用不了
s1:控制灯开关和闭合 s2:将灯调为0% s3:25% s4:50% s5:75% s6:100%
程序:
#include "config.h"
#include "gpio.h"
#include "UART.h"
#include "delay.h"
#include "stdio.h"
#include "STC8xxxx.H"
#include "string.h"
#include "light.h"
#include "my_uart.h"
#include "timer.h"
unsigned long timer0_count = 0;
unsigned char PWM_T = 0; //0-250占空比控制变
unsigned char current_brightness = 0; //当前亮度
unsigned char light_switch_state = 0; //灯开关状态
signed int brightness = 0;
unsigned char key_open = 1;
#define IT_HZ 100000 //中断频率
#define TIM0_VALUE 65536UL - (MAIN_Fosc / IT_HZ)
void light_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //结构定义
TIM_InitTypeDef TIM_InitStructure; //结构定义
/************************ P33 IO口配置 ****************************/
GPIO_InitStructure.Pin = LIGHT_PIN; //指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7, 或操作
GPIO_InitStructure.Mode = GPIO_PullUp; //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
GPIO_Inilize(LIGHT_PORT,&GPIO_InitStructure); //初始化
/************************ 定时器配置 ****************************/
TIM_InitStructure.TIM_Mode = TIM_16BitAutoReload; //指定工作模式, TIM_16BitAutoReload,TIM_16Bit,TIM_8BitAutoReload,TIM_16BitAutoReloadNoMask
TIM_InitStructure.TIM_Priority = Priority_0; //指定中断优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
TIM_InitStructure.TIM_Interrupt = ENABLE; //中断是否允许, ENABLE或DISABLE
TIM_InitStructure.TIM_ClkSource = TIM_CLOCK_1T; //指定时钟源, TIM_CLOCK_1T,TIM_CLOCK_12T,TIM_CLOCK_Ext
TIM_InitStructure.TIM_ClkOut = DISABLE; //是否输出高速脉冲, ENABLE或DISABLE
// TIM_InitStructure.TIM_Value = 65536UL - (MAIN_Fosc / 100000UL); //初值,
TIM_InitStructure.TIM_Value = TIM0_VALUE; //初值,
TIM_InitStructure.TIM_Run = ENABLE; //是否初始化后启动定时器, ENABLE或DISABLE
Timer_Inilize(Timer0,&TIM_InitStructure); //初始化Timer0 Timer0,Timer1,Timer2,Timer3,Timer4
}
//设置高电平占空比
//num: 0-100%
void set_duty_cycle(unsigned char num)
{
current_brightness = num;
if(num > 0)
{
light_switch_state = 1;
}
else
{
light_switch_state = 0;
}
PWM_T = (float)(num / 100.0)*250;
}
/********************* Timer0中断函数************************/
void timer0_int (void) interrupt TIMER0_VECTOR
{
timer0_count++; //每次定时器溢出加1
if(timer0_count==250) //PWM周期 100个单位
{
timer0_count=0; //使t=0,开始新的PWM周期
LIGHT = 1; //开灯
}
if(PWM_T==timer0_count) //按照当前占空比切换输出为高电平
{
LIGHT = 0; //关灯
}
}
//获取灯光占空比
//返回值: 0-100
int get_light_pwm(void)
{
return PWM_T*100/250;
// return 0;
}
void light_open(void) //通电时亮灯为25%
{
EA = 1;
light_switch_state = 1;
set_duty_cycle(25); //设置占空比
brightness = 25;
}
#define ADC_CHANNEL 4 // 使用P5.4作为ADC输入,对应ADC通道4
#define VCC 5000 // 供电电压,单位mV
// 初始化系统
void System_Init(void)
{
P5M1 = 0x00; // 设置P5.4为模拟输入 引脚1
P5M0 = 0x10;
// 设置ADC
ADC_CONTR = 0x80 + (ADC_CHANNEL << 3); // 选择ADC通道4
ADC_RES = 0x00;
ADC_RESL = 0x00;
}
// 读取ADC值
int Read_ADC(void)
{
ADC_CONTR |= 0x80; // 开始ADC转换
while(ADC_CONTR & 0x80); // 等待转换完成
return (ADC_RES << 8) | ADC_RESL; // 返回10位ADC结果
}
// 判断按键
void Check_Keys(int adc_value)
{
if (adc_value > 0 && adc_value < 170) //按键s1
{
if(light_switch_state==1) //如果灯是开的就关闭
{
light_switch_state=0;
EA = 0;
set_duty_cycle(0);
LIGHT = 0;
}
else //灯是灭的就打开并设置为50%
{
EA = 1;
light_switch_state=1;
brightness = 50;
set_duty_cycle(brightness); //设置占空比
}
}
else if (adc_value >= 171 && adc_value < 340) //按键s2 设置为0
{
brightness = 0;
set_duty_cycle(brightness);
// 按键2
}
else if (adc_value >= 341 && adc_value < 510) //按键s3 设置为25%
{
brightness = 25;
set_duty_cycle(brightness);
// 按键3
}
else if (adc_value >= 511 && adc_value < 680) //按键s4 设置为50%
{
brightness = 50;
set_duty_cycle(brightness);
// 按键4
}
else if (adc_value >= 681 && adc_value < 850) //按键s5 设置为75%
{
brightness = 75;
set_duty_cycle(brightness);
// 按键5
}
else if(adc_value >=851 && adc_value <1005) //按键s6 设置为100%
{
brightness = 100;
set_duty_cycle(brightness);
}
}
// 主函数
void main(void)
{
System_Init();
light_init(); //使用定时器0作pwm功能
EA = 0;
delay_ms(5000);
light_open();
while (1)
{
int adc_value = Read_ADC(); // 读取ADC值
delay_ms(1);
Check_Keys(adc_value); // 检查按键
}
}
|