|
用的是stc8g1k08a单片机芯片,用adc把0-5v的模拟信号转成pwm输出,占空比小于10%的时候会有点轻微的闪烁我就在占空比小于10%的时候把它关掉,但是在那个临界的时候led会一直闪是为什么呀,我后面测了led闪烁时的电压,它一直在九点多v到十点多v变化,是adc的精度不够吗还是什么原因呀,代码是之前一位工程师写的,但是他离职了,总工就扔给我一个菜鸡了
#include "intrins.h"
#include "main.h"
#include "Adc.h"
#define CYCLE 0x1000
AboutPwmPara PwmPara; //PWM相关参数
void delay_us(int n)
{
while (--n);
}
void delay()
{
int i, j;
for (i=0; i<10; i++)
for (j=0; j<1; j++);
}
/*******************************************************************************
** 函数名称: Main_Init()
** 函数功能: 参数初始化
** 函数参数:
**
**
** 返 回 值: 无
*******************************************************************************/
void Main()
{
P3M0 = 0x00;
P3M1 = 0x00;
PwmPara.PwmCnt = 0; //Pwm占空比计数器
PwmPara.PwmPercentage = 0;
PwmPara.PwmLast = 0;
TMOD = 0x00;
TL0 = 0xa3; //65536-11.0592M/12/1000
TH0 = 0xff;
TR0 = 1; //启动定时器
ET0 = 1; //使能定时器中断
Adc_Init();
EADC = 1; //开启ADC中断
EA = 1;
while(1)
{
PwmPara.PwmNow = AdcPara.AdcVal/1024*100;
if(PwmPara.PwmLast == 0)
PwmPara.PwmLast = PwmPara.PwmNow;
PwmPara.PwmLast = PwmPara.PwmLast*0.8f+PwmPara.PwmNow*0.2f;
PwmPara.PwmPercentage = (uint8_t)(PwmPara.PwmLast+0.5f);
}
}
/*******************************************************************************
** 函数名称: Time0()
** 函数功能: 定时器0中断处理函数
** 函数参数:
**
**
** 返 回 值: 无
*******************************************************************************/
void TM0_Isr() interrupt 1
{
if(PwmPara.PwmCnt>100)
PwmPara.PwmCnt = 0;
PwmPara.PwmCnt++;
if(PwmPara.PwmPercentage <10)
{
PwmPara.PwmPercentage = 0;
P32 = 0;
}
if((PwmPara.PwmCnt>0)&&(PwmPara.PwmCnt < PwmPara.PwmPercentage))
{
if(P32 == 0)
P32 = 1;
}
else
{
if(P32 == 1)
P32 = 0;
}
}
adc文件
AboutAdcContrVal AdcContrVal; //控制寄存器参数
AboutAdcCfgVal AdcCfgVal; //配置寄存器参数
AboutAdcTimVal AdcTimVal; //时序寄存器
AboutAdcPara AdcPara; //ADC相关参数
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/*******************************************************************************
** 函数名称: Adc_Init()
** 函数功能: 初始化
** 函数参数:
**
**
** 返 回 值: 无
*******************************************************************************/
void Adc_Init(void)
{
AdcContrVal.AllVal = 0;
AdcCfgVal.AllVal = 0;
// AdcTimVal.AllVal = 0;
AdcPara.ConvertCnt = 0; //连续转换次数计数器
AdcPara.AdcVal = 0; //ADC转换值
AdcContrVal.ControlPara.Adc_Power = 1; //打开ADC电源
AdcContrVal.ControlPara.Adc_Chs = ADC_CHS_P55; //选择ADC引脚
AdcContrVal.ControlPara.Adc_Start = 1; //开启ADC转换
AdcCfgVal.ControlPara.Speed = 0x0f; //将ADC系统时钟设定为SYSclk/2/16
AdcCfgVal.ControlPara.Resfmt = 1; //将ADC转换结果右对齐
// ADCTIM = AdcTimVal.AllVal; //设置 ADC 内部时序
ADCCFG = AdcCfgVal.AllVal; //寄存器赋值
ADC_CONTR = AdcContrVal.AllVal; //寄存器赋值
}
/*******************************************************************************
** 函数名称: Adc_Isr()
** 函数功能: ADC转换中断处理函数
** 函数参数:
**
**
** 返 回 值: 无
*******************************************************************************/
void Adc_Isr() interrupt 5
{
if(AdcPara.ConvertCnt >= CONVERT_TIMES)
{
AdcPara.ConvertCnt = 0;
AdcPara.SunVal = 0; //ADC转换值
for(AdcPara.Temp=0;AdcPara.Temp<CONVERT_TIMES;AdcPara.Temp++)
{
AdcPara.SunVal += AdcPara.ConvertVal[AdcPara.Temp];
AdcPara.ConvertVal[AdcPara.Temp] = 0;
}
if(AdcPara.SunVal != 0)
AdcPara.AdcVal = AdcPara.SunVal/CONVERT_TIMES;
else
AdcPara.AdcVal = 0;
}
AdcPara.ConvertVal[AdcPara.ConvertCnt] = ADC_RES*256 + ADC_RESL;
AdcPara.ConvertCnt++;
AdcContrVal.ControlPara.Adc_Flag = 0; //中断标志位清0
AdcContrVal.ControlPara.Adc_Start = 1; //开启ADC转换
ADC_CONTR = AdcContrVal.AllVal; //寄存器赋值
} |
|