你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32基础设计---ADC转换(DMA方式)

[复制链接]
STMCU小助手 发布时间:2023-1-4 21:36
本文简单介绍了STM32F103C8,通过DMA方式读取ADC并通过串口中断向电脑端打印出当前电源ADC的值。

现在先将设计过程的主要步骤介绍如下:
                1,串口配置
                2,中断配置
                3,DMA配置
                4,ADC配置
                5,中断服务函数
                6,主函数

       先总结下博主在这次基础设计中犯的错误,在中断初始化函数中,没有将中断通道使能,导致电脑端没有接收到数据,发现后就去检查串口初始化函数了,结果没有发现错误,而是检查了一遍代码才发现错误。发现串口无法工作后,先核查初始化函数,如果问题没有解决,第二步,如果是串口中断方式,接下来检查,中断初始化函数,如果是串口查询方式,接下来检查主函数的串口查询代码。

接下来详细介绍各个步骤:

1,串口配置
  1. void usart_init(void)
  2. {
  3.         GPIO_InitTypeDef GPIO_usart;定义GPIO结构体
  4.         USART_InitTypeDef USART_usart;定义串口结构体
  5.        
  6.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1 ,ENABLE);使能外设时钟
  7.        
  8.         GPIO_usart.GPIO_Pin = GPIO_Pin_9;
  9.         GPIO_usart.GPIO_Mode = GPIO_Mode_AF_PP;
  10.         GPIO_usart.GPIO_Speed = GPIO_Speed_50MHz;
  11.         GPIO_Init(GPIOA,&GPIO_usart);配置发送口
  12.        
  13.         GPIO_usart.GPIO_Pin = GPIO_Pin_10;
  14.         GPIO_usart.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  15.         GPIO_usart.GPIO_Speed = GPIO_Speed_50MHz;
  16.         GPIO_Init(GPIOA,&GPIO_usart);配置接受口
  17.        
  18.         USART_usart.USART_BaudRate = 115200;设置传输波特率
  19.         USART_usart.USART_WordLength = USART_WordLength_8b;设置串口发送字长
  20.         USART_usart.USART_StopBits = USART_StopBits_1;设置停止位
  21.         USART_usart.USART_Parity = USART_Parity_No;不进行奇偶校验
  22.         USART_usart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;硬件流使能
  23.         USART_usart.USART_Mode = USART_Mode_Tx;设置为发送模式
  24.         USART_Init(USART1,&USART_usart);初始化串口寄存器
  25.        
  26.         USART_Cmd(USART1,ENABLE);串口使能
  27.         USART_ClearFlag(USART1,USART_FLAG_TC);清除已发送位,防止第一位发不出去
  28. }
复制代码

2,中断配置

  1. void nvic_init(void)
  2. {
  3.         NVIC_InitTypeDef nvic_usart;定义中断结构体
  4.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);设置中断分组
  5.         nvic_usart.NVIC_IRQChannel = USART1_IRQn;制定中断服务函数通道
  6.         nvic_usart.NVIC_IRQChannelPreemptionPriority = 1;抢占优先级1
  7.         nvic_usart.NVIC_IRQChannelSubPriority = 0;子优先级0
  8.         nvic_usart.NVIC_IRQChannelCmd = ENABLE;通道使能
  9.         NVIC_Init(&nvic_usart);中断寄存器初始化
  10. }
复制代码


3,DMA配置
  1. void dma_init(void)
  2. {
  3.         DMA_InitTypeDef dma;定义DMA结构体
  4.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);打开时钟
  5.        
  6.         DMA_DeInit(DMA1_Channel1);现将DMA,通道1寄存器复位
  7.         dma.DMA_PeripheralBaseAddr = (u32)&ADC1->DR;设置外设地址
  8.         dma.DMA_MemoryBaseAddr = (uint32_t)ADC_Value;设置存储器地址
  9.         dma.DMA_DIR = DMA_DIR_PeripheralSRC;设置传输方向为 外设到存储器
  10.         dma.DMA_BufferSize = 2;数据缓冲为设置为2
  11.         dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable;外设地址固定
  12.         dma.DMA_MemoryInc = DMA_MemoryInc_Enable;寄存器地址自增
  13.         dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;外设数据位宽度半字
  14.         dma.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;存储器数据位宽度半字
  15.         dma.DMA_Mode = DMA_Mode_Circular;DMA工作在循环模式
  16.         dma.DMA_Priority = DMA_Priority_High;DMA通道为高优先级
  17.         dma.DMA_M2M = DMA_M2M_Disable;内存到内存传输使能
  18.         DMA_Init(DMA1_Channel1,&dma);初始化DMA寄存器
  19.        
  20.         //DMA_Cmd(DMA1_Channel1,ENABLE);使能通道1 (笔者把这句放到主函数中了,在这里写也行,只不过是笔者认为放到主函数中便于理解)
  21. }
复制代码


4,adc配置
  1. void adc_init(void)
  2. {
  3.         ADC_InitTypeDef adc;定义adc结构体
  4.         GPIO_InitTypeDef adc_gpio;定义GPIO结构体
  5.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOB,ENABLE);使能外设
  6.        
  7.         adc_gpio.GPIO_Pin = GPIO_Pin_1;
  8.         adc_gpio.GPIO_Mode = GPIO_Mode_AIN;
  9.         GPIO_Init(GPIOB,&adc_gpio);使能ADC的测试通道
  10.        
  11.         ADC_DeInit(ADC1);复位ADC1寄存器
  12.         ADC_TempSensorVrefintCmd(ENABLE);使能内部参照电压
  13.         adc.ADC_Mode = ADC_Mode_Independent;ADC工作在独立模式
  14.         adc.ADC_ScanConvMode = ENABLE;使用扫描模式
  15.         adc.ADC_ContinuousConvMode = ENABLE;使用连续转换模式
  16.         adc.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;不使用外部触发工作模式
  17.         adc.ADC_DataAlign = ADC_DataAlign_Right;数据设置为右对齐
  18.         adc.ADC_NbrOfChannel = 2;两个转换通道
  19.        
  20.         ADC_Init(ADC1,&adc);初始化寄存器
  21.        
  22.         ADC_RegularChannelConfig(ADC1,ADC_Channel_9,1,ADC_SampleTime_239Cycles5);对通道9采样(电源电压)
  23.         ADC_RegularChannelConfig(ADC1,ADC_Channel_17,2,ADC_SampleTime_239Cycles5);对通道11采样(参考电压)
  24.        
  25.         //ADC_DMACmd(ADC1,ENABLE);ADC 的DMA通道使能
  26.        
  27.         //ADC_Cmd(ADC1,ENABLE);ADC使能
  28.        
  29.         //ADC_ResetCalibration(ADC1);复位ADC1的校准寄存器
  30.         //while(ADC_GetResetCalibrationStatus(ADC1));等待复位完成
  31.        
  32.         //ADC_StartCalibration(ADC1);开始ADC1校准
  33.         //while(ADC_GetCalibrationStatus(ADC1));等待校准完成
  34.        
  35.         //ADC_SoftwareStartConvCmd(ADC1,ENABLE);ADC1的软件转换使能(注:这些注释的部分我放到主函数里了,放在这里也行,只不过,我感觉我那样便于理解)
  36. }
复制代码


5,中断服务函数
  1. void USART1_IRQHandler(void)
  2. {
  3.         if(USART1->SR & USART_SR_TC)判断是否能发送数据
  4.         {
  5.                 USART1->DR = TxBuff[TxCount++];笔者将转换到的电压值存到TxBuff[0]中了
  6.                 if(TxCount == Count)等到传完一次数据,就退出中断
  7.                 {
  8.                         USART1->CR1 &= ~USART_CR1_TXEIE;
  9.                 }
  10.         }
  11. }
复制代码


6,主函数
  1. int main()
  2. {
  3.         usart_init();串口初始化
  4.         nvic_init();中断初始化
  5.         dma_init();DMA初始化
  6.         adc_init();ADC初始化
  7.         DMA_Cmd(DMA1_Channel1,ENABLE);//见上文
  8.         ADC_DMACmd(ADC1,ENABLE);同上
  9.        
  10.         ADC_Cmd(ADC1,ENABLE);同上
  11.        
  12.         ADC_ResetCalibration(ADC1);同上
  13.         while(ADC_GetResetCalibrationStatus(ADC1));同上
  14.        
  15.         ADC_StartCalibration(ADC1);同上
  16.         while(ADC_GetCalibrationStatus(ADC1));同上
  17.        
  18.         ADC_SoftwareStartConvCmd(ADC1,ENABLE);同上
  19.         while(1)循环打印电压值
  20.         {
  21.                 Voltage_Printf();用于打印电压
  22.                 //PrintString("\r\nprint data!!\r\n");
  23.                 delay(1000);延时
  24.         }
复制代码


  1. void Voltage_Printf(void)
  2. {
  3.         Battery = (uint16_t)(2.0f *ADC_Value[0] / ADC_Value[1] *1.2f * 100);根据参考电压按比例计算电源电压
  4.         PrintString("\r\n当前电压值的一百倍:");
  5.         PrintU16(Battery);
  6.         PrintString("V");
  7. }
复制代码


下面粘贴完整代码
  1. #include<stm32f10x.h>

  2. uint16_t ADC_Value[2];
  3. static uint16_t Battery=0;
  4. uint8_t TxCount = 0;
  5. uint8_t Count = 0;
  6. static uint8_t TxBuff[250];
  7. volatile uint8_t RxBuffer[50];

  8. void delay(uint32_t n)
  9. {
  10.         int i,j;
  11.         for(i=0;i<n;i++)
  12.                 for(j=0;j<8500;j++);
  13. }

  14. void usart_init(void)
  15. {
  16.         GPIO_InitTypeDef GPIO_usart;
  17.         USART_InitTypeDef USART_usart;
  18.        
  19.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1 ,ENABLE);
  20.        
  21.         GPIO_usart.GPIO_Pin = GPIO_Pin_9;
  22.         GPIO_usart.GPIO_Mode = GPIO_Mode_AF_PP;
  23.         GPIO_usart.GPIO_Speed = GPIO_Speed_50MHz;
  24.         GPIO_Init(GPIOA,&GPIO_usart);
  25.        
  26.         GPIO_usart.GPIO_Pin = GPIO_Pin_10;
  27.         GPIO_usart.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  28.         GPIO_usart.GPIO_Speed = GPIO_Speed_50MHz;
  29.         GPIO_Init(GPIOA,&GPIO_usart);
  30.        
  31.         USART_usart.USART_BaudRate = 115200;
  32.         USART_usart.USART_WordLength = USART_WordLength_8b;
  33.         USART_usart.USART_StopBits = USART_StopBits_1;
  34.         USART_usart.USART_Parity = USART_Parity_No;
  35.         USART_usart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  36.         USART_usart.USART_Mode = USART_Mode_Tx;
  37.         USART_Init(USART1,&USART_usart);
  38.        
  39.         USART_Cmd(USART1,ENABLE);
  40.         USART_ClearFlag(USART1,USART_FLAG_TC);
  41. }
  42.        
  43. void nvic_init(void)
  44. {
  45.         NVIC_InitTypeDef nvic_usart;
  46.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  47.         nvic_usart.NVIC_IRQChannel = USART1_IRQn;
  48.         nvic_usart.NVIC_IRQChannelPreemptionPriority = 1;
  49.         nvic_usart.NVIC_IRQChannelSubPriority = 0;
  50.         nvic_usart.NVIC_IRQChannelCmd = ENABLE;
  51.         NVIC_Init(&nvic_usart);
  52. }
  53.        
  54. void dma_init(void)
  55. {
  56.         DMA_InitTypeDef dma;
  57.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
  58.        
  59.         DMA_DeInit(DMA1_Channel1);
  60.         dma.DMA_PeripheralBaseAddr = (u32)&ADC1->DR;
  61.         dma.DMA_MemoryBaseAddr = (uint32_t)ADC_Value;
  62.         dma.DMA_DIR = DMA_DIR_PeripheralSRC;
  63.         dma.DMA_BufferSize = 2;
  64.         dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  65.         dma.DMA_MemoryInc = DMA_MemoryInc_Enable;
  66.         dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  67.         dma.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  68.         dma.DMA_Mode = DMA_Mode_Circular;
  69.         dma.DMA_Priority = DMA_Priority_High;
  70.         dma.DMA_M2M = DMA_M2M_Disable;
  71.         DMA_Init(DMA1_Channel1,&dma);
  72.        
  73.         //DMA_Cmd(DMA1_Channel1,ENABLE);
  74. }
  75. void adc_init(void)
  76. {
  77.         ADC_InitTypeDef adc;
  78.         GPIO_InitTypeDef adc_gpio;
  79.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOB,ENABLE);
  80.        
  81.         adc_gpio.GPIO_Pin = GPIO_Pin_1;
  82.         adc_gpio.GPIO_Mode = GPIO_Mode_AIN;
  83.         GPIO_Init(GPIOB,&adc_gpio);
  84.        
  85.         ADC_DeInit(ADC1);
  86.         ADC_TempSensorVrefintCmd(ENABLE);
  87.         adc.ADC_Mode = ADC_Mode_Independent;
  88.         adc.ADC_ScanConvMode = ENABLE;
  89.         adc.ADC_ContinuousConvMode = ENABLE;
  90.         adc.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
  91.         adc.ADC_DataAlign = ADC_DataAlign_Right;
  92.         adc.ADC_NbrOfChannel = 2;
  93.        
  94.         ADC_Init(ADC1,&adc);
  95.        
  96.         ADC_RegularChannelConfig(ADC1,ADC_Channel_9,1,ADC_SampleTime_239Cycles5);
  97.         ADC_RegularChannelConfig(ADC1,ADC_Channel_17,2,ADC_SampleTime_239Cycles5);
  98.        
  99.         //ADC_DMACmd(ADC1,ENABLE);
  100.        
  101.         //ADC_Cmd(ADC1,ENABLE);
  102.        
  103.         //ADC_ResetCalibration(ADC1);
  104.         //while(ADC_GetResetCalibrationStatus(ADC1));
  105.        
  106.         //ADC_StartCalibration(ADC1);
  107.         //while(ADC_GetCalibrationStatus(ADC1));
  108.        
  109.         //ADC_SoftwareStartConvCmd(ADC1,ENABLE);
  110. }
  111. void PrintHexU8(uint8_t data)
  112. {
  113.         TxBuff[Count++] = data;
  114.         if(!(USART1->CR1 & USART_CR1_TXEIE))
  115.                 USART_ITConfig(USART1,USART_IT_TXE,ENABLE);
  116. }

  117. void PrintString(uint8_t *s)
  118. {
  119.         uint8_t *p;
  120.         p=s;
  121.         while(*p!= '\0')
  122.         {
  123.                 PrintHexU8(*p);
  124.                 p++;
  125.         }
  126. }

  127. void PrintU16(uint16_t num)
  128. {
  129.         uint8_t w5,w4,w3,w2,w1;
  130.          w5 = num % 100000/10000;  
  131.    w4 = num % 10000/1000;  
  132.    w3 = num % 1000/100;  
  133.    w2 = num % 100/10;  
  134.    w1 = num % 10;  
  135.    PrintHexU8('0' + w5);  
  136.    PrintHexU8('0' + w4);  
  137.    PrintHexU8('0' + w3);  
  138.    PrintHexU8('0' + w2);  
  139.    PrintHexU8('0' + w1);
  140. }

  141. void Voltage_Printf(void)
  142. {
  143.         Battery = (uint16_t)(2.0f *ADC_Value[0] / ADC_Value[1] *1.2f * 100);
  144.         PrintString("\r\nµ±Ç°µç³Øµçѹֵһ°Ù±¶£º");
  145.         PrintU16(Battery);
  146.         PrintString("V");
  147. }
  148. int main()
  149. {
  150.         usart_init();
  151.         nvic_init();
  152.         dma_init();
  153.         adc_init();
  154.         DMA_Cmd(DMA1_Channel1,ENABLE);
  155.         ADC_DMACmd(ADC1,ENABLE);
  156.        
  157.         ADC_Cmd(ADC1,ENABLE);
  158.        
  159.         ADC_ResetCalibration(ADC1);
  160.         while(ADC_GetResetCalibrationStatus(ADC1));
  161.        
  162.         ADC_StartCalibration(ADC1);
  163.         while(ADC_GetCalibrationStatus(ADC1));
  164.        
  165.         ADC_SoftwareStartConvCmd(ADC1,ENABLE);
  166.         while(1)
  167.         {
  168.                 Voltage_Printf();
  169.                 //PrintString("\r\nprint data!!\r\n");
  170.                 delay(1000);
  171.         }
  172. }
  173.        
  174. void USART1_IRQHandler(void)
  175. {
  176.         if(USART1->SR & USART_SR_TC)
  177.         {
  178.                 USART1->DR = TxBuff[TxCount++];
  179.                 if(TxCount == Count)
  180.                 {
  181.                         USART1->CR1 &= ~USART_CR1_TXEIE;
  182.                 }
  183.         }
  184.        
  185.         if(USART1->SR & USART_SR_RXNE)
  186.         {
  187.                 volatile int8_t com_data;
  188.                 com_data = USART1->DR;
  189.         }
  190. }
复制代码


————————————————
版权声明:家安


收藏 评论0 发布时间:2023-1-4 21:36

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版