历史上的今天
返回首页

历史上的今天

今天是:2024年12月31日(星期二)

正在发生

2021年12月31日 | STM32F103单片机ADC功能使用

2021-12-31 来源:eefocus

12位ADC是一种逐次逼近型模拟数字转换器。它有多达18个通道,可测量16个外部和2个内部信号源。各通道的A/D转换可以单次、连续、扫描或间断模式执行。ADC的结果可以左对齐或右对齐方式存储在16位数据寄存器中。


模拟看门狗特性允许应用程序检测输入电压是否超出用户定义的高/低阀值。


ADC的输入时钟不得超过14MHz,它是由PCLK2经分频产生。


ADC 主要特征


● 12位分辨率


● 转换结束、注入转换结束和发生模拟看门狗事件时产生中断


● 单次和连续转换模式


● 从通道0到通道n的自动扫描模式


● 自校准


● 带内嵌数据一致性的数据对齐


● 采样间隔可以按通道分别编程


● 规则转换和注入转换均有外部触发选项


● 间断模式


● 双重模式(带2个或以上ADC的器件)


下面就用代码演示如何设置ADC单次转换模式


void ADCx_Init(void)

{

    GPIO_InitTypeDef GPIO_InitStructure;

    ADC_InitTypeDef ADC_InitStructure;


    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1, ENABLE);

    RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M


    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1| GPIO_Pin_2| GPIO_Pin_3| GPIO_Pin_4| GPIO_Pin_5; //PA1

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOA, &GPIO_InitStructure);


    ADC_DeInit(ADC1);


    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //工作在独立模式

    ADC_InitStructure.ADC_ScanConvMode = DISABLE; //单通道模式

    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //单次转换模式

    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //软件触发

    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //右对齐

    ADC_InitStructure.ADC_NbrOfChannel = 1; //规则转换ADC通道数

    ADC_Init(ADC1, &ADC_InitStructure);


    ADC_Cmd(ADC1, ENABLE); //使能ADC1


    ADC_ResetCalibration(ADC1); //复位校准

    while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束

    ADC_StartCalibration(ADC1); //开启AD校准

    while(ADC_GetCalibrationStatus(ADC1)); //等待校准结束


}


首先初始化IO口,这里的初始化的是ADC抓换通道的0–5,对应的IO口PA0到PA5,将这6个IO口这是为模拟输入模式。接下来在将这几个口设置为ADC口,在设置之前首先将ADC模式复位,然后将ADC设置为单通道单词转换模式,也就是每次只转换一个通道,转换一次后就停止转换,直到接收到下一次转换命令为止。开始转换的命令是由软件来设置的。


ADC口初始化好之后,还需要一个读取转换结果的函数,用于读取指定通道的转换值。


//获取ADC值

//ch:通道号

u16 Get_Adc( u8 ch )

{

    ADC_RegularChannelConfig( ADC1, ch, 1, ADC_SampleTime_239Cycles5 ); //ADC1,ADC通道,采样时间为239.5周期

    ADC_SoftwareStartConvCmd( ADC1, ENABLE ); //使能ADC1软件启动转换

    while( !ADC_GetFlagStatus( ADC1, ADC_FLAG_EOC ) ); //等待转换结束

    return ADC_GetConversionValue( ADC1 ); //返回最近一次ADC1规则组的转换结果

}


u16 Get_Adc_Average( u8 ch, u8 times )

{

    u32 temp_val = 0;

    u8 t;

    for( t = 0; t < times; t++ )

    {

        temp_val += Get_Adc( ch );

        delay_ms( 5 );

    }

    return temp_val / times;

}


Get_Adc()函数用于读取指定通道的ADC转换值,这里的通道必须是初始化函数中初始化过的通道,这个函数每次只读取一次通道值,为了确保转换结果的正确性,需要多次读取通道值取平均值,所以这里Get_Adc_Average()函数就是用来设置多次读取指定通道值,然后取平均值后返回。比如可以设置读取通道1,100次然后取平均值。ADC相关的设置函数就初始化好了,接下来在主函数中调用Get_Adc_Average()函数就可以读取通道值了。


int main(void)

{

    u16 adcx = 0;

    float temp;

    delay_init();        //延时函数初始化

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

    uart_init(115200);

    LED_Init();



    LED0 = 1;

    LED1 = 1;

    delay_ms(500);

    LED0 = 0;

    LED1 = 0;


    ADCx_Init();


    printf("ADC test!!!rn");

    while(1)

    {

        adcx = Get_Adc_Average(ADC_Channel_0, 10);

        printf("ch0       num: %drn", adcx);

        temp = (float)adcx * (3.3 / 4096);

        adcx = temp * 1000;

        printf("ch0 adc value: %drn", adcx);


        adcx = Get_Adc_Average(ADC_Channel_1, 10);

        printf("ch1       num: %drn", adcx);

        temp = (float)adcx * (3.3 / 4096);

        adcx = temp * 1000;

        printf("ch1 adc value: %drn", adcx);


        adcx = Get_Adc_Average(ADC_Channel_2, 10);

        printf("ch2       num: %drn", adcx);

        temp = (float)adcx * (3.3 / 4096);

        adcx = temp * 1000;

        printf("ch2 adc value: %drn", adcx);


        adcx = Get_Adc_Average(ADC_Channel_3, 10);

        printf("ch3       num: %drn", adcx);

        temp = (float)adcx * (3.3 / 4096);

        adcx = temp * 1000;

        printf("ch3 adc value: %drn", adcx);


        adcx = Get_Adc_Average(ADC_Channel_4, 10);

        printf("ch4       num: %drn", adcx);

        temp = (float)adcx * (3.3 / 4096);

        adcx = temp * 1000;

        printf("ch4 adc value: %drn", adcx);


        adcx = Get_Adc_Average(ADC_Channel_5, 10);

        printf("ch5       num: %drn", adcx);

        temp = (float)adcx * (3.3 / 4096);

        adcx = temp * 1000;

        printf("ch5 adc value: %drn", adcx);


        LED0 = !LED0;

        delay_ms(500);

    }

}


在主函数中依次读取通道0到通道5的值,读取10次取平均值,然后将转换后的值打印出来。由于ADC为12位,所以转换后的最大值为4096,对应的最大电压值为3.3V,为了方便观察,将转换后的值换换位电压值。

推荐阅读

史海拾趣

Compound Photonics公司的发展小趣事

在公司发展初期,Compound Photonics曾专注于一款微投显示模组的研发。然而,这个项目并未如预期般顺利,最终宣告失败。面对挫折,公司并没有放弃,而是迅速调整战略,转向LCoS方向。这一决策不仅让公司避免了进一步的损失,还为其在LCoS领域的发展打开了新的大门。

FCI [First Components International]公司的发展小趣事

尽管在Micro LED领域遭遇了挫折,但Compound Photonics并没有因此沉沦。相反,公司凭借其在LCoS领域的深厚技术积累和良好的市场口碑,吸引了众多潜在合作伙伴的关注。其中,Snap公司表现出了强烈的收购意向。这一消息传出后,Compound Photonics的市场价值得到了进一步提升,公司的发展前景也变得更加广阔。

这五个故事展示了Compound Photonics公司在电子行业里发展起来的一些关键节点和重大事件。从收购Syntax-Brillian开启微显示领域之路,到微投显示模组项目失利后转向LCoS方向,再到成为业内知名LCoS方案商并与Lumus合作,以及与Plessey合作开发Micro LED产品遭遇Meta竞争,最后到Snap的收购意向,每一个故事都反映了公司在不同阶段的挑战与机遇。通过这些故事,我们可以看到Compound Photonics公司在电子行业里不断进取、创新发展的精神风貌。

G-Mag Usa公司的发展小趣事

随着全球对环境保护意识的增强,G-Mag在2010年决定实施绿色转型战略。公司投入大量资源研发环保型电子产品和制造工艺,如开发可降解材料用于产品包装、优化生产线以减少能源消耗和废弃物排放等。同时,G-Mag还积极推广循环经济理念,与上下游企业合作建立废旧电子产品回收体系。这些举措不仅提升了G-Mag的品牌形象,还为其赢得了更多消费者的青睐和政府的支持。在绿色转型的推动下,G-Mag实现了可持续发展与经济效益的双赢。

昭华(CHA)公司的发展小趣事

昭华公司一直注重品牌建设和市场拓展。他们通过参加各种行业展会、举办技术研讨会等方式,积极宣传公司的产品和技术优势。同时,昭华公司还加强了与客户的沟通和合作,深入了解客户需求并提供定制化的解决方案。这些努力使得昭华公司的品牌知名度不断提升,市场份额也逐渐扩大。

启英泰伦(Chiplntelli)公司的发展小趣事

随着市场竞争的加剧和消费者需求的多样化,启英泰伦不断调整和创新其市场策略。为了解决“装得起”这一问题,公司选择了将智能语音识别技术集成到智能插座上的新路径。这一策略不仅降低了功耗的严格约束,还对方案的尺寸和成本进行了优化。此外,启英泰伦还针对不同应用场景进行细分,如照明、风扇等产品交互比较简单的领域,开发了相应的芯片和解决方案。这些创新策略使启英泰伦能够更好地满足市场需求,保持了在行业内的领先地位。

Dytran Instruments Inc公司的发展小趣事

2022年5月,英国思百吉集团(Spectris)以5.4亿美元的价格收购了Dytran。这次收购是思百吉集团进一步扩大其在传感器领域的布局的重要举措。作为思百吉集团旗下的子公司,Dytran将继续保持其独立性和品牌特色,同时借助思百吉的全球资源和市场渠道,加速其业务发展和市场拓展。

在被收购后,Dytran与思百吉旗下的其他品牌进行了业务整合。通过共享研发资源、优化供应链、拓展销售渠道等方式,Dytran实现了与思百吉旗下品牌的协同发展。这不仅提高了公司的运营效率和市场竞争力,还为客户提供了更加全面和优质的服务。

问答坊 | AI 解惑

输入电阻和输出电阻(纠结了好长时间,看完就懂了)

     关于输入电阻和输出电阻,纠结了好长时间,现在终于明白了,拿出来给大家看一下,呵呵      输入电阻是用来衡量放大器对信号源的影响的一个性能指标。输入电阻越大,表明放大器从信号源取的电流 ...…

查看全部问答>

evc4.0能开发wince5.0的程序么--急!

evc4.0能开发运行在wince5.0的程序么? 对于bin文件有什么要求么? 还是有其他别的注意事项啊? 原来运行在wince4.2上正常的程序,到wince5.0就不是有效的wince程序了是什么问题, 详细介绍最好啊!!!…

查看全部问答>

春节后,开始找工作

我在深圳,大家有没有好的推荐? 顶者有分噢!…

查看全部问答>

初学者问题

刚学单片机,在仿真时,出现connection to target lost是什么原因? 还有个问题,在eeworld上传图片时,提示出现不明错误,无法上传,本来有图片的话,能把问题描述的更清楚些。…

查看全部问答>

为什么用vs2005还是EVC4SP4编译刚建好的例子时总提示要连接ActiveSync呢?

为什么用vs2005还是EVC4SP4编译刚建好的例子时总提示要连接ActiveSync呢? 环境是WINCE5 ,ActiveSync装的版本是4.2中文版. 是不是调试的时候一定要插上硬件呢?不插上可以调试WINCE5平台下开发的程序吗? EVC4下的错误提示是: An application ...…

查看全部问答>

望请指点啊

我用的是四位八段共阳数码管 程序如下 显示有问题 module smg_wela(                                 clk,             &nbs ...…

查看全部问答>

求用最小系板和DS18B20来测量温度并在12864液晶上显示

 各位玩MSP430的大大们,求助啦~! 想用MSP430最小系统版和DS18B20来测量温度,且在12864LCD液晶上面显现出数据来! 可不可以帮忙写下代码啊! 急用啊! 下面的CX-1A系统版的原理图 小弟感激不尽! [ 本帖最后由 z9 ...…

查看全部问答>

处理一批2.4寸TFT屏,每人限购10PCS,有美女,有送!

2.4寸TFT屏,带触摸屏,ILI9320驱动!引脚定义如下图: 前天 12:21 上传下载附件 (146.79 KB) 屏的图片如下: 前天 12:21 上传下载附件 (73.57 KB) 前天 12:21 上传下载附件 (63.51 KB) 显示效果如下: ...…

查看全部问答>

说说解决EXP430G2与MSP430FR5xxx调试问题

这几天发现一件怪事,之前的EXP430G2不能下载程序了,找了一块板还是同样的问题。 ”Fatal error:failed to re-initalize Session aborte!\" 1.4打印的信息是: Sat Nov 03, 2012 19:20:19: Firmware version 30066536 Sat Nov 03, 2012 19:20 ...…

查看全部问答>

Proteus 如何利用matlab 2013A CCS5.2 实现仿真调试

楼主 求解1  Proteus  的.hex文件不能用只能用cof文件        求解2  Proteus  DSP 16位的存储单元  为啥存储器寄存器区都是 8位一个单元        求 ...…

查看全部问答>