找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 673|回复: 6
收起左侧

STM32单片机使用寄存器配置ADC读取不到数据问题

[复制链接]
ID:831673 发表于 2023-3-22 00:46 | 显示全部楼层 |阅读模式
如题,楼主在使用stm32寄存器配置ADC电压采样,使用中断获取采样数据,实际效果中,adc配置后无法读取不到寄存器DR的值,单片机使用stm32f103vet6

单片机代码如下:
使用的gpio口是PC1,对应的adc1是通道11
引脚配置:
  1. void ADC_GPIO_INIT(void)
  2. {

  3. SET_BIT(RCC->APB2ENR,RCC_APB2ENR_IOPCEN);//**开GPIOC端口时钟
  4. GPIOC->CRL &= ~(0xf<<4);//**模拟输入模式 PC1
  5. }
复制代码

ADC初始化配置
  1. void ADC_Mode_Config(void)
  2. {
  3. SET_BIT(RCC->APB2ENR,RCC_APB2ENR_ADC1EN);//**开ADC1外设时钟
  4. SET_BIT(RCC->CFGR,RCC_CFGR_ADCPRE_DIV6);//设置ADC分频因子,6分频,72/6=12MHZ[indent]
  5. ADC1->CR1=0;//**初始化
  6. ADC1->CR2=0;[/indent][indent]
  7. SET_BIT(ADC1->CR1,ADC_CR1_EOCIE);//**转换结束后产生中断
  8. SET_BIT(ADC1->CR2,ADC_CR2_CONT);//**配置连续转换模式

  9. ADC1->SMPR1|=7<<(3*1);//**采样周期为239.5个周期
  10. ADC1->SQR1|=0<<20;//**1个转换

  11. SET_BIT(ADC1->CR2,ADC_CR2_ADON);//**开启AD转换器[/indent][indent]
  12. SET_BIT(ADC1->CR2,ADC_CR2_RSTCAL);//**使能复位校准
  13. while(READ_BIT(ADC1->CR2,ADC_CR2_RSTCAL));//**等待校准结束
  14. SET_BIT(ADC1->CR2,ADC_CR2_CAL);//**使能A/D校准
  15. while(READ_BIT(ADC1->CR2,ADC_CR2_CAL));//**等待校准结束[/indent]
  16. ADC1->SQR3&=0XFFFFFFE0
  17. ADC1->SQR3|=11;//**通道配置

  18. NVIC_SetPriority(ADC1_2_IRQn, 1);//配置中断优先级
  19. NVIC_EnableIRQ(ADC1_2_IRQn);//开中断

  20. }

复制代码
中断函数
  1. void ADC_IRQHandler(void)
  2. {        
  3. if (READ_BIT(ADC1->SR,ADC_SR_EOC))
  4.   {
  5.   // 读取ADC的转换值
  6.   ADC_ConvertedValue = ADC1->DR;
  7.   }
  8. }
复制代码

主函数:
1.png

问题出在ADC初始化函ADC_Mode_Config()上,我的想法是转换完成后EOCIE产生一个中断,在中断中读取DR寄存器的值,实际效果是读取到的dr的值始终为0:
2.png


也试图使用软件开启配置:
ADC1->CR2|=7<<17; //软件控制转换
ADC1->CR2|=1<<20; //使用外部触发(SWSTART)
SET_BIT(ADC1->CR2,ADC_CR2_SWSTAR);//**软件设置开始转换
while(!(ADC1->SR&1<<1)); //等待完成

当开启外部触发EXTTRIG,并配置EXTSEL为SWSTART,在中断优先级配置后启用SWSTART,串口接收不到任何信息。
回复

使用道具 举报

ID:301191 发表于 2023-3-22 15:12 | 显示全部楼层
顶一下
回复

使用道具 举报

ID:123289 发表于 2023-3-22 16:27 | 显示全部楼层
再读CPU手册,特别关注AD部分。
回复

使用道具 举报

ID:831673 发表于 2023-3-23 00:22 | 显示全部楼层
yzwzfyz 发表于 2023-3-22 16:27
再读CPU手册,特别关注AD部分。

找到原因了,问题出在中断上
回复

使用道具 举报

ID:831673 发表于 2023-3-23 00:31 | 显示全部楼层
问题补充更新:
我将ADC的中断触发关闭,设置成单次转换模式,直接在转换结束后读取DR寄存器的值,没有通过触发来读取,发现可以正常读取到ADC的值:
  1. static void ADCx_Mode_Config(void)
  2. {
  3. RCC->APB2ENR|=1<<9; //ADC1 时钟使能
  4. RCC->APB2RSTR|=1<<9; //ADC1 复位
  5. RCC->APB2RSTR&=~(1<<9);//复位结束
  6. RCC->CFGR&=~(3<<14); //分频因子清零
  7. //SYSCLK/DIV2=12M ADC 时钟设置为 12M,ADC 最大时钟不能超过 14M!
  8. //否则将导致 ADC 准确度下降!
  9. RCC->CFGR|=2<<14;
  10. ADC1->CR1&=0XF0FFFF; //工作模式清零
  11. ADC1->CR1|=0<<16; //独立工作模式
  12. ADC1->CR1&=~(1<<8); //非扫描模式
  13.        
  14. ADC1->CR2&=~(1<<1);//单次转换模式
  15.        
  16. //ADC1->CR2|=1<<1; //连续转换模式
  17. //ADC1->CR1|=1<<5;//开中断
  18.        
  19. ADC1->CR2&=~(7<<17);
  20. ADC1->CR2|=7<<17; //软件控制转换
  21. ADC1->CR2|=1<<20; //使用用外部触发(SWSTART)!!! 必须使用一个事件来触发
  22. ADC1->CR2&=~(1<<11); //右对齐
  23. ADC1->SQR1&=~(0XF<<20);
  24. ADC1->SQR1|=0<<20; //1 个转换在规则序列中 也就是只转换规则序列 1
  25. //设置通道 11 的采样时间
  26. ADC1->SMPR1&=~(3*1); //通道 11 采样时间清空
  27. ADC1->SMPR1|=7<<(3*1); //通道 11 239.5 周期,提高采样时间可以提高精确度
  28. ADC1->CR2|=1<<0; //开启 AD 转换器
  29. ADC1->CR2|=1<<3; //使能复位校准
  30. while(ADC1->CR2&1<<3); //等待校准结束
  31. //该位由软件设置并由硬件清除。在校准寄存器被初始化后该位将被清除。
  32. ADC1->CR2|=1<<2; //开启 AD 校准
  33. while(ADC1->CR2&1<<2); //等待校准结束
  34. //该位由软件设置以开始校准,并在校准结束时由硬件清除
  35. }

  36. u16 Get_Adc(void)
  37. {
  38. ADC1->SQR3&=0XFFFFFFE0;//???? 1 ?? ch
  39. ADC1->SQR3|=ADC_Channel_11;
  40. ADC1->CR2|=1<<22; //????????
  41. while(!(ADC1->SR&1<<1)); //??????
  42. return ADC1->DR; //?? adc ?
  43. }
复制代码


由此可见在串口调试助手中无法输出内容是由于中断的问题
以下是中断EOCIE的说明:

EOCIE:允许产生EOC中断 (Interrupt enable for EOC)
该位由软件设置和清除,用于禁止或允许转换结束后产生中断。
0:禁止EOC中断;
1:允许EOC中断。当硬件设置EOC位时产生中断。

那么,理论上ADC转化完成后将产生EOC中断,进入中断函数,在中断函数中读取到DR的值,而实际效果是ADC在中断这里卡死,具体原因还在寻找。
回复

使用道具 举报

ID:831673 发表于 2023-3-23 01:14 | 显示全部楼层
找到最终原因了,是我中断函数名写错导致EOC中断产生后没法进入中断函数。
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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