OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 11696|回复: 3

惊奇发现!!原子哥帮忙看看ADC问题

[复制链接]

267

主题

376

帖子

0

精华

QQ游客

积分
1079
金钱
1079
注册时间
2012-2-23
在线时间
12 小时
发表于 2012-2-24 09:02:24 | 显示全部楼层 |阅读模式
ADC搞了好几天了,一直不太明白怎么设置通道,原子哥的ADC例程里面给的是默认CH0~3,我把主函数中的adcx=Get_Adc(ADC_CH0);改成adcx=Get_Adc(10);,也就是使用CH10(PC0),居然也能用,这个让我很费解,PORTC的时钟我都是没开,通道10的采样时间也没设置,怎么也能正常工作啊?然后我参考例程写了一个通道CH8~CH11的程序,也能正常工作,但是用CH0~CH3也能工作,PA口的时钟也没开,下面是我写的ADC初始化程序,主程序中adcx=Get_Adc(10);,为什么我没有设置的ADC通道也能正常工作??
void Adc_Init(void)
{
    RCC->APB2ENR|=1<<3;        //使能PORTB时钟
    GPIOB->CRL&=0xFFFFFF00;    //PB0 PB1设置为模拟输入
    RCC->APB2ENR|=1<<4;        //使能PORTC时钟
    GPIOC->CRL&=0xFFFFFF00;    //PC0 PC1设置为模拟输入
    RCC->APB2ENR|=1<<9;        //使能ADC1时钟
    RCC->APB2RSTR|=1<<9;    //ADC1复位                
    RCC->APB2RSTR&=~(1<<9);    //复位结束
    RCC->CFGR&=~(3<<14);    //分频因子清零
    //SYSCLK/DIV2=12MHz,ADC时钟设置为12MHz
    //ADC的时钟最大不能超过14MHz,否则将导致ADC准确度下降!
    RCC->CFGR|=2<<14;        //PCLK2=72MHz,6分频后作为ADC时钟

    ADC1->CR1&=0xF0FFFF;    //工作模式清零
    ADC1->CR1|=0<<16;        //独立工作模式
    ADC1->CR1|=(1<<8);        //扫描模式
    ADC1->CR2|=(1<<1);        //连续转换模式
    ADC1->CR2&=~(7<<17);
    ADC1->CR2|=7<<17;        //软件控制转换
    ADC1->CR2|=1<<20;        //使用外部触发 SWSTART,必须使用一个事件来触发
    ADC1->CR2&=~(1<<11);    //右对齐

    ADC1->SQR1&=~(0xF<<20);
    ADC1->SQR1&=0<<20;        //1个转换在规则序列中,也就是只转换规则序列1

    //设置通道0~3的采样时间
    ADC1->SMPR2&=0x00FFFFFF;//通道8  9  采样时间清空
    ADC1->SMPR1&=0xFFFFFF00;//通道10 11 采样时间清空
    ADC1->SMPR2|=7<<24;        //通道8   239.5周期,提高采样时间可以提高采样精确度
    ADC1->SMPR2|=7<<27;        //通道9   239.5周期,提高采样时间可以提高采样精确度
    ADC1->SMPR1|=7<<3;        //通道10  239.5周期,提高采样时间可以提高采样精确度
    ADC1->SMPR1|=7<<0;        //通道11  239.5周期,提高采样时间可以提高采样精确度

    ADC1->CR2|=1<<0;        //开启ADC转换器
    ADC1->CR2|=1<<3;        //使能复位校准
    while(ADC1->CR2&(1<<3));//等待校准结束
    //该位由软件设置并由硬件清除,在校准寄存器被初始化后该位将被清除
    ADC1->CR2|=1<<2;        //开启AD校准
    while(ADC1->CR2&(1<<2));//等待校准结束
    //该位由软件设置以开始校准,并在校准结束时由硬件清除
}

//获得ADC值
//ch:通道值 8~11
u16 Get_Adc(u8 ch)
{
    //设置转换序列
    ADC1->SQR3&=0xFFFFFFE0;    //规则序列 1
    ADC1->SQR3|=ch;            //通道 ch
    ADC1->CR2|=1<<22;        //启动规则转换通道
    while(!(ADC1->SR&(1<<1)));//等待转换结束
    return ADC1->DR;        //返回ADC值
}
在主函数中Get_Adc(0)和Get_Adc(10)都能工作采样到电压,请原子解释下原因,我搞了好几天,实在没想明白!

我用网友suqingxiao 发的 STM32测试程序 ADC+DMA+串口发送。全代码奉献(操作寄存器)http://www.openedv.com/posts/list/1772.htm 试了一下,也出现同样的问题!


上图中画红线的地方什么意思?后面的括号里的0~17又指什么??SQRx寄存器中是0有效中还是1有效啊?
根据ADC1->SQR3&=0xFFFFFFE0;//规则序列 1
ADC1->SQR3|=ch; //通道ch
如果是规则序列 2,就应该写成 ADC1->SQR3&=0xFFFFFE0F;吗?那ADC1->SQR3|=ch;这里的ch又怎么写?
问题有点多,一大早就起来发的,希望原子帮忙解答一下!十分感谢!!


正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

38

主题

527

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1424
金钱
1424
注册时间
2011-11-27
在线时间
122 小时
发表于 2012-2-24 10:21:07 | 显示全部楼层
我也遇到过没有打开端口时钟,但可以使用端口的情况。
永远保持一颗学习的心态。
回复 支持 反对

使用道具 举报

5

主题

43

帖子

0

精华

初级会员

Rank: 2

积分
83
金钱
83
注册时间
2011-12-2
在线时间
0 小时
发表于 2012-3-4 11:09:40 | 显示全部楼层
我也遇到过这类问题,求解中!!
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165371
金钱
165371
注册时间
2010-12-1
在线时间
2110 小时
发表于 2012-3-4 13:21:16 | 显示全部楼层
回复【楼主位】xujiangyu0619:
---------------------------------
能采集到电压不奇怪.因为ADC和IO是两个独立的外设,理论上只要开启了ADC,就能读各个通道的值,只是这个值准不准确的问题了.IO设置只是用来选择连接方式.
0~17指的是ADC的通道.SQR既不是0有效,也不是1有效,而是一个存储通道值的寄存器.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-25 01:12

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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