找回密码
 立即注册
查看: 108|回复: 2

关于STC8G1K08的多路ADC采样问题

[复制链接]

该用户从未签到

2

主题

4

回帖

34

积分

新手上路

积分
34
发表于 2024-3-29 22:08:49 | 显示全部楼层 |阅读模式
由于项目需要用到5路的ADC采样,但是我发现多路通道之间的采样值会互相影响,是需要在程序上进行处理吗
回复 送花

使用道具 举报

  • TA的每日心情
    奋斗
    6 小时前
  • 签到天数: 144 天

    [LV.7]常住居民III

    27

    主题

    1355

    回帖

    4215

    积分

    论坛元老

    积分
    4215
    发表于 2024-3-29 22:35:15 | 显示全部楼层
    用附件的例子烧录到芯片里试试,通过串口打印采集结果,STC8系列单片机都可以参考

    16路ADC轮询-每路16次ADC转换取中间8次求平均值-串口1返回结果.zip

    10.86 KB, 下载次数: 10

    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    2

    主题

    4

    回帖

    34

    积分

    新手上路

    积分
    34
     楼主| 发表于 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; //同上
                                    }
                    }                     
            }
    }

    回复 支持 反对 送花

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

    GMT+8, 2024-5-20 15:44 , Processed in 0.061708 second(s), 40 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

    快速回复 返回顶部 返回列表