ts2000 发表于 2016-12-5 10:37:39

好像也太复杂了吧。

yuwentry 发表于 2017-5-10 10:28:47

非常谢谢@飞龙xyj 的回复,也解决了我的多通道ADC采集值不对的问题,在切换通道前加一句清除通道语句即可.同时贴出我的代码备他人参考。
void ADC_Init(void)          //初始化ADC,即初始化ADC
{
       
        CLK_PCKENR2 |= SETBIT3;   //开ADC时钟
        ADC_CR2 = 0x08;             // A/D结果数据右对齐
ADC_CR1 = 0x00;             // ADC时钟=主时钟/2=1MHZ
                              // ADC转换模式=单次
                              // 禁止ADC转换
        ADC_TDRH = 0x00;                                     //禁止施密特触发,对应的通道置1
        //ADC_TDRL = 0x38;            //0b00111000 对应3、4、5通道禁止
        ADC_TDRL = 0x30;            //0b00111000 对应3、4、5通道禁止,打开3通道
        ADC_CR1 = 0x01;         // CR1寄存器的最低位置1,使能ADC转换
        Delay_us(8);                        // 延时一段时间,至少7uS,保证ADC模块的
       
}
u16 ADC_Get_Voltage(unsigned char channel)//获取对应通道电压量化值
{
        u16 vt;
        u16 DRL,DRH;
        ADC_CSR = ADC_CSR & 0x80;             // 清除通道
        ADC_CSR = ADC_CSR | channel;          // 选择通道
        ADC_CR1 = ADC_CR1 | 0x01; // 再次将CR1寄存器的最低位置1
                              // 使能ADC转换
        while((ADC_CSR & 0x80) == 0); // 等待ADC结束
        DRL = ADC_DRL;            // 读出ADC结果的低8位
DRH = ADC_DRH;            // 读出ADC结果的高8位       
        ADC_CSR &= CLRBIT7;//清转换结束标志       
        vt=(DRH<<8)|DRL;//量化值,需要 Vt/1024*Vs(Vs=3.3V )
        vt=(int)(vt*VIN*100/1024);//内部参考输入电压,100是小数点后2位都化为整数
        //vt=(int)(vt*VIN*1000/1024);//内部参考输入电压,1000是小数点后3位都化为整数
        return vt;
}

ST007 发表于 2017-11-5 17:36:37

飞龙xyj 发表于 2015-6-30 19:01
楼主您好,我今天用连续扫描模式调通了8个模拟通道(AIN0-AIN7)的AD采集,看了下您的代码,发现有两处问题 ...

非常感谢,按照“飞龙xyj”的方法,增加了如下指令,      
      /* Clear the ADC1 channels */
         ADC1->CSR &= (uint8_t)(~ADC1_CSR_CH);
      /* Select the ADC1 channel */
      ADC1->CSR |= (uint8_t)(ADC1_CHANNEL_7);
终于解决了ADC单次扫描,输出缓存寄存器无数据的问题,非常感谢!

ST007 发表于 2017-11-5 17:37:00

飞龙xyj 发表于 2015-6-30 19:01
楼主您好,我今天用连续扫描模式调通了8个模拟通道(AIN0-AIN7)的AD采集,看了下您的代码,发现有两处问题 ...

非常感谢,按照“飞龙xyj”的方法,增加了如下指令,      
      /* Clear the ADC1 channels */
         ADC1->CSR &= (uint8_t)(~ADC1_CSR_CH);
      /* Select the ADC1 channel */
      ADC1->CSR |= (uint8_t)(ADC1_CHANNEL_7);
终于解决了ADC单次扫描,输出缓存寄存器无数据的问题,非常感谢!

ST007 发表于 2017-11-5 17:42:59

使用的芯片为:STM8S003F3P,ADC配置为单次扫描模式,并设置ADC转化完成中断,具体如下:
void ADC1_Config(void)
{
        ADC1_DeInit();
/* Clear the SPSEL bits */
ADC1->CR1 &= (uint8_t)(0x8F); // 1000 1111
/* Set the prescaler of ADC : fADC1 = fcpu/4 =4MHz*/
ADC1->CR1 |= (uint8_t)(ADC1_PRESSEL_FCPU_D4);
        /* Set the single conversion mode */
ADC1->CR1 &= (uint8_t)(0xFD);// 1111 1101
/* Set the continous conversion mode */
        //ADC1->CR1 |=(uint8_t)(0x02);
        /* Clear the align bit */
ADC1->CR2 &= (uint8_t)(0xF7);// 1111 0111
/* Configure the data alignment */
ADC1->CR2 |= (uint8_t)(ADC1_ALIGN_RIGHT);
       
        /* 如果定时器触发模式被选定(定时器事件作为触发源,而不是外部引脚),
        那么推荐在ADC完成设置之后启动定时器和在关闭ADC之前先停止定时器。*/
/* Clear the external trigger selection bits */
ADC1->CR2 &= (uint8_t)(0xCF);// 1100 1111
        /* Select TIM1 TRGO as external trigger souce */
// ADC1->CR2 |= (uint8_t)(ADC1_EXTTRIG_TIM);
/* Enable the selected external trigger */
        //ADC1->CR2 |= (uint8_t)(0x40);// 0100 0000
//ADC1->CR2 &= (uint8_t)(0xBF);// 1011 1111
/* Enable the ADC1 scan mode */
        //ADC1->CR2 |= (uint8_t)(ADC1_CR2_SCAN);
        ADC1_ScanModeCmd(ENABLE);

/* Enables the ADC1 data store into the Data Buffer registers
rather than in the Data Register */
        ADC1->CR3 |= ADC1_CR3_DBUF;
        /* Clear OVR flag status */
       ADC1->CR3 &= (uint8_t)(~ADC1_CR3_OVR);
//        ADC1_ClearITPendingBit(ADC1_IT_EOC);

        /* Disable EOC/AWD interrupts of ADC1 */
        //ADC1->CSR &= (uint8_t)(0xCF);// 1100 1111
        ADC1_ITConfig(ADC1_IT_EOCIE,ENABLE);//ENABLE
        ADC1_ITConfig(ADC1_IT_AWDIE,DISABLE);
//ADC1_ITConfig((ADC1_IT_AWDIE|ADC1_IT_EOCIE),DISABLE);
        /* Clear the ADC1 channels */
        ADC1->CSR &= (uint8_t)(0xF0);//
/* Select a ADC1 channel to be converted */
//        ADC1->CSR |= (uint8_t)(ADC1_CHANNEL_0);//6//5//4//3//2
/* Clear EOC flag status */
ADC1->CSR &= (uint8_t)(0x7F);// 0111 1111
       
/* Disable the Schmitt Trigger of all channels on ADC1*/
ADC1->TDRL |= (uint8_t)0xFF;
ADC1->TDRH |= (uint8_t)0xFF;
        /*Enables or Disables the ADC1 peripheral*/
        ADC1_Cmd(ENABLE);
        Delay_us(500);//第一次上电后,等待ADC1的稳定
        /*启动一次ADC1采样及转换*/
        ADC1_Cmd(ENABLE);
}
而且我是在TIM4设置的400us时基中断中重新开启ADC1,让ADC1再进行一次新的扫描,
然后在ADC转化完成中断里,进行清除flag标志,以及做新的设置,具体如下:
INTERRUPT_HANDLER(ADC1_IRQHandler, 22)
{
/* In order to detect unexpected events during development,
                it is recommended to set a breakpoint on the following instruction.
*/


//ADC1_ClearFlag(ADC1_FLAG_EOC);//ADC1_CR3_OVR
ADC1_ClearITPendingBit(ADC1_IT_EOC);
/* Clear OVR flag status */
ADC1->CR3 &= (uint8_t)(~ADC1_CR3_OVR);

/* Clear the ADC1 channels */
ADC1->CSR &= (uint8_t)(~ADC1_CSR_CH);
/* Select the ADC1 channel */
ADC1->CSR |= (uint8_t)(ADC1_CHANNEL_6);

//GPIO_WriteReverse(GPIOA,GPIO_PIN_2);
// return;
}

代码运行正常,结果满足预期,希望对其他小伙伴,提供帮助!

hans918 发表于 2019-12-26 11:06:08

谢谢

nsx811 发表于 2020-8-29 11:24:29

学习中,感谢分亨!
页: 1 [2]
查看完整版本: STM8S ADC多通道连续扫描问题