zt997354616 发表于 2024-3-29 22:08:49

关于STC8G1K08的多路ADC采样问题

由于项目需要用到5路的ADC采样,但是我发现多路通道之间的采样值会互相影响,是需要在程序上进行处理吗

乘风飞扬 发表于 2024-3-29 22:35:15

用附件的例子烧录到芯片里试试,通过串口打印采集结果,STC8系列单片机都可以参考

zt997354616 发表于 2024-3-30 16:43:24

乘风飞扬 发表于 2024-3-29 22:35
用附件的例子烧录到芯片里试试,通过串口打印采集结果,STC8系列单片机都可以参考 ...

能帮忙看一下程序吗,串口发出来的值又是准确的,/*************        PCA配置函数        **************/
/*****************************************/

void        PCA_config( u8 clk, u8 wide)
{
        CR = 0;   //停止PCA定时器
        CMOD = (CMOD & ~0x0E) | ((clk & 7) << 1);                // PCA时钟选择, 0: 12T,1: 2T, 2: Timer0溢出率, 3: ECI引脚输入, 4: 1T,5: 4T,6: 6T,7: 8T
        PCA0_PWM(wide);        //PWM宽度        0: 8位PWM,1: 7位PWM,2: 6位PWM,3: 10位PWM                       
        P_SW1 = (P_SW1 & ~0x30) | 0x00;        // 将PCA/PWM切换到 P5.5(ECI) P3.1(CCP0) P3.3(CCP1) P5.4(CCP2)
        P1n_push_pull(0x02);        //头文件的宏, P1.1 设置为推挽输出                       
        CH = 0;
        CL = 0;
        CR   = 1;        // 运行PCA定时器
}

void        UpdatePwm( u16 pwm_value)
{
                PCA_PWM0 = (PCA_PWM0 & ~0x32) | (u8)((pwm_value >> 4) & 0x30);
                CCAP0H = (u8)pwm_value;
        //        PWM0_NORMAL();               
}
/*****************************************/
/*****************************************/

/*************        PID函数        ******************/
/*****************************************/

typedef struct PID_Value
{
    int   KP;
    int   KI;
    int          KD;
    int   Inck;
    int   EkSum;
    int   Vref;
    int   Vin;
    int   Ek;
    int   Ek_1;
    int   Ek_2;
    int   dacOutAmp;
    int   Acutual_pidout;
}PID_ValueStr;

PID_ValueStr pidStr;

void PID_initial(void)
{
    pidStr.KP=10;
    pidStr.KI=1;

}

void PID_Caculate()
{                      
    pidStr.Ek=243-VCC ;                                                        
        pidStr.Inck=pidStr.KP*(pidStr.Ek- pidStr.Ek_1) + pidStr.KI*pidStr.Ek;
    pidStr.Ek_2 = pidStr.Ek_1;                                          
    pidStr.Ek_1 = pidStr.Ek;                                                                                                  
        pidStr.dacOutAmp -= pidStr.Inck;                       
        if(pidStr.dacOutAmp<128)                                                          
    pidStr.dacOutAmp = 128;
    if(pidStr.dacOutAmp>243)
    pidStr.dacOutAmp = 243;                                                                                                                  
    pwm_value=pidStr.dacOutAmp;                                                       
}


/*****************************************/
/*****************************************/


/*************        中断INT0函数        **********/
/*****************************************/
void INT0_Isr() interrupt 0
{   
       P37=0;
       FLAG=30;                                       
}
/*****************************************/
/*****************************************/
/*************        ADC函数        **************/
/*************************************/

uint Get_ADCResult(u8 channel)
{       
           ADC_RES = 0;
        ADC_RESL = 0;
        ADC_CONTR = (ADC_CONTR & 0xf0) | 0x40 | channel;
        //delay1us();                        //对ADC_CONTR操作后等待会儿再访问
        while ((ADC_CONTR & 0x20)==0);
        ADC_CONTR &=~0x20;
        ADC1_DATA=(ADC_RES<<8)|ADC_RESL;
    return ADC1_DATA;       
}

void ADC_Isr() interrupt 5
{       
        EADC=0;
    ADC_CONTR &= ~0x20;                         //清中断标志
           VCC=(ADC_RES<<8)|ADC_RESL;               
        PID_Caculate();                                                                         
        UpdatePwm(pwm_value);                                                //更新PWM       
}

/*****************************************/
/*****************************************/
/*********************************************
/*函数名称:Timer0_Config(u8 mode, u16 time)
/*函数功能:Timer0配置函数
/*输入参数:mode:速度模式
/*                                        mode=1, 1T模式; mode=2,12T模式
/*                                        time:定时时间
/*        1T模式(max=5.9ms):1ms=1000,2ms=500,5ms=200
/*        12T模式(max=71ms):1ms=1000,10ms=100
/*返回值:无
*********************************************/
void Timer0_Config()
{
       
        AUXR |= 0x80;                //定时器0为1T模式
        TH0 = 0xFD;
        TL0 = 0xE4;
        TMOD &= 0xF0;                //设置定时器为模式0,16位自动重装载
        TR0 = 1;                                //启动定时器
        ET0 = 1;                                //打开定时器中断
}



void Timer0() interrupt TIMER0_VECTOR
{       
        ADC_RES = 0;
        ADC_RESL = 0;
        ADC_CONTR = (ADC_CONTR & 0xf0) | 0x40 | 4;
        while ((ADC_CONTR & 0x20)==0);
        ADC_CONTR &=~0x20;
        EADC=1;       
        ADC_RES = 0;
        ADC_RESL = 0;
        ADC_CONTR = (ADC_CONTR & 0xf0) | 0x40 | 4;   
}




/*************************************
/*函数名称:LED_Init()
/*函数功能:LED初始化函数
/*输入参数:无
/*返回值:无
*************************************/
void LED_Init(void)
{
        //P1M1 &= ~(1<<2);        P1M0 |= (1<<2);        //设置P1.2为推挽输出
        //P1M1 &= ~(1<<3);        P1M0 |= (1<<3);        //设置P1.3为推挽输出
        LED1 = 1;                //初始化LED1
        LED2 = 1;                //初始化LED2
}

/*************************************
/*函数名称:LED_Toggle(unsigned char led_id)
/*函数功能:LED状态取反函数
/*输入参数:LED序号(led_id=1~n)
/*返回值:无
*************************************/
void LED_Toggle(unsigned char led_id)
{
        switch(led_id)
        {
                case 1:
                        LED1 = ~LED1;                //LED1状态取反
                        break;
                case 2:
                        LED2 = ~LED2;                //LED2状态取反
                        break;
        }
}


/******************** 主函数 **************************/
void main(void)
{
        P0M1 = 0;   P0M0 = 0;   //设置为准双向口
        P1M1 = 0;   P1M0 = 0;   //设置为准双向口
        P2M1 = 0;   P2M0 = 0;   //设置为准双向口
        P3M1 = 0;   P3M0 = 0;   //设置为准双向口
    P1M0 = (P1M0 & ~0xf8) | 0x04; P1M1 = (P1M1 & ~0x04) | 0xf8;           //P1.2推挽输出 P1.3 P1.4 P1.5 P1.6 P1.7 高阻输入
    P3M0 |= 0xac; P3M1 &= ~0xac;           //        P3.2 P3.3 P3.5 P3.7推挽输出
        PID_initial();
        PCA_config(4,0);
        LED_Init();                                        //LED初始化函数
        Timer0_Config();                        //定时器0配置,12T模式,time=10ms                                                                                                 
        P_SW2 |= 0x80;                               
    ADCTIM = 0x0a;                              
    P_SW2 &= 0x7f;                                                                //设置ADC内部时序
    ADCCFG = 0x20;                              //设置ADC时钟为系统时钟/2/16
    ADC_CONTR = 0x80;                           //使能ADC模块
    IT0 = 1;                                    //使能INT0下降沿中断
    EX0 = 1;                                    //使能INT0中断
        IPH=0x03;
        IP=0x21;
    EA = 1;                                                                                //允许总中断       
       
        while(1)
        { u8 i ;
          u16 j ;
               for(i=5; i<8; i++)
                {
                        Get_ADCResult(i);
                        j=Get_ADCResult(i);
                        if((i==6)&&(j<512))
                                {
                                                P37=0;//主要是这里只有一开始上电的时候给6通道低于512的电压P37才会置低,一开是给高电压话后续不论给什么电压都不会置低
                                }
                        if((i==7)&&(j<512))
                                {
                                                  P37=0; //同上
                                }
                }                 
        }
}

页: [1]
查看完整版本: 关于STC8G1K08的多路ADC采样问题