搜索
12
返回列表 发新帖
楼主: 朗峰

[已解决] STM8S ADC多通道连续扫描问题

[复制链接]

该用户从未签到

27

主题

1912

帖子

42

蝴蝶豆

论坛元老

最后登录
2022-7-11
发表于 2016-12-5 10:37:39 | 显示全部楼层
好像也太复杂了吧。
回复 支持 反对

使用道具 举报

该用户从未签到

0

主题

3

帖子

0

蝴蝶豆

初级会员

最后登录
2020-9-3
发表于 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;
}
回复 支持 反对

使用道具 举报

该用户从未签到

3

主题

10

帖子

0

蝴蝶豆

新手上路

最后登录
2020-10-14
发表于 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单次扫描,输出缓存寄存器无数据的问题,非常感谢!
回复 支持 反对

使用道具 举报

该用户从未签到

3

主题

10

帖子

0

蝴蝶豆

新手上路

最后登录
2020-10-14
发表于 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单次扫描,输出缓存寄存器无数据的问题,非常感谢!
回复 支持 反对

使用道具 举报

该用户从未签到

3

主题

10

帖子

0

蝴蝶豆

新手上路

最后登录
2020-10-14
发表于 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;
}

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

回复 支持 反对

使用道具 举报

该用户从未签到

5

主题

19

帖子

0

蝴蝶豆

初级会员

最后登录
2021-3-14
发表于 2019-12-26 11:06:08 | 显示全部楼层
谢谢
回复

使用道具 举报

该用户从未签到

0

主题

1

帖子

0

蝴蝶豆

新手上路

最后登录
2020-8-29
发表于 2020-8-29 11:24:29 | 显示全部楼层
学习中,感谢分亨!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条

Archiver|手机版|小黑屋|论坛-意法半导体STM32/STM8技术社区

GMT+8, 2024-4-28 23:17 , Processed in 0.158598 second(s), 34 queries .

Powered by Discuz! X3.4

Copyright © 2001-2024, Tencent Cloud.

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