搜索
bottom↓
回复: 9

急急!求STM32L15 ADC多通道连续采样DMA 例程序,有偿答谢!

[复制链接]

出0入0汤圆

发表于 2020-4-17 21:24:48 | 显示全部楼层 |阅读模式
急急!求STM32L151 ADC多通道连续采样DMA  例程序,有偿答谢!
软件触发模式

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出100入143汤圆

发表于 2020-4-17 21:45:44 | 显示全部楼层
  1. /* INCLUDES ----------------------------------------------------------------- */
  2. #include "includes.h"
  3. #include "analogio.h"

  4. /**
  5. * @defgroup AnalogIO
  6. * @brief Analog input and output
  7. * @{
  8. */

  9. /* TYPEDEFS ----------------------------------------------------------------- */

  10. /**
  11. * @brief Analog Port and Pin define
  12. */
  13. typedef struct
  14. {
  15.   GPIO_TypeDef* GPIOx;
  16.   uint16_t      GPIO_Pin;
  17. }AIO_PortPin_t;

  18. /* MACROS  ------------------------------------------------------------------ */

  19. /* CONSTANTS  --------------------------------------------------------------- */

  20. // PC0_ADC_IN10(W_AD1),  PC1_ADC_IN11(W_AD2),  PC2_ADC_IN12(W_AD3),  PC3_ADC_IN13(W_AD4)
  21. // PA4_ADC_IN4(W_AD5),   PA5_ADC_IN5(W_AD6),   PA6_ADC_IN6(W_AD7),   PA7_ADC_IN7(W_AD8),

  22. static const AIO_PortPin_t AIN_PORT_PIN[AIO_CH_NUM_IN] = {
  23.   {GPIOC, GPIO_Pin_0}, {GPIOC, GPIO_Pin_1}, {GPIOC, GPIO_Pin_2}, {GPIOC, GPIO_Pin_3},
  24.   {GPIOA, GPIO_Pin_4}, {GPIOA, GPIO_Pin_5}, {GPIOA, GPIO_Pin_6}, {GPIOA, GPIO_Pin_7},
  25. };

  26. /* GLOBAL VARIABLES --------------------------------------------------------- */

  27. /* GLOBAL FUNCTIONS --------------------------------------------------------- */

  28. /* LOCAL VARIABLES ---------------------------------------------------------- */

  29. // ADC sample DMA buffer must >= 3
  30. #define AIN_BUFF_SIZE 8
  31. static volatile uint16_t s_usAinBuffer[AIN_BUFF_SIZE][AIO_CH_NUM_IN];

  32. /* LOCAL FUNCTIONS ---------------------------------------------------------- */
  33. static void     aio_sort_bubble(uint16_t *pbuf, uint8_t len);
  34. static uint16_t aio_sample_avg(uint16_t *pbuf, uint8_t len);

  35. static void AIO_InLowLevelInit(void);
  36. static void AIO_OutLowLevelInit(void);


  37. /**
  38. * @brief  Init
  39. * @param  None
  40. * @return Init status
  41. * @retval AIO_OK Init success
  42. */
  43. AIO_ERROR_t AIO_Init(void)
  44. {
  45.   AIO_InLowLevelInit();
  46.   AIO_OutLowLevelInit();

  47.   return AIO_OK;
  48. }

  49. /**
  50. * @brief  Start or Stop analog in sample
  51. * @param  status 1-Start,0-Stop
  52. * @retval None
  53. */
  54. void AIO_SetInStatus(uint8_t status)
  55. {
  56.   if (status)
  57.   {
  58.     AIO_InLowLevelInit();
  59.   }
  60.   else
  61.   {
  62.     ADC_DeInit(ADC1);
  63.     DMA_DeInit(DMA1_Channel1);
  64.   }
  65. }

  66. /**
  67. * @brief  Get analog in voltage collect
  68. * @param[in]  AIN_TYPE_INx: (AIO_TYPE_IN_MIN < x < AIO_TYPE_IN_MAX)
  69. * @param[out] VOL_MV: mv sampled signal, max 3300mV
  70. * @retval AIO_OK Success
  71. */
  72. AIO_ERROR_t AIO_GetInVoltage(AIO_TYPE_t AIO_TYPE_INx, uint16_t *VOL_MV)
  73. {
  74.   uint8_t ofs;
  75.   uint32_t val;
  76.   uint16_t buff[AIN_BUFF_SIZE];

  77.   if ((AIO_TYPE_INx <= AIO_TYPE_IN_MIN) || (AIO_TYPE_INx >= AIO_TYPE_IN_MAX) || (AIN_BUFF_SIZE <= 2))
  78.     return AIO_ERROR_Param;

  79.   ofs = AIO_TYPE_INx - AIO_TYPE_IN1;

  80.   for (uint8_t i = 0; i < AIN_BUFF_SIZE; i++)
  81.     buff[i] = s_usAinBuffer[i][ofs];

  82.   aio_sort_bubble(&buff[0], AIN_BUFF_SIZE);

  83.   val = aio_sample_avg(&buff[AIN_BUFF_SIZE / 4], AIN_BUFF_SIZE / 2);
  84.   val = (val * 3300ul) / 0xFFF;

  85.   if (VOL_MV)
  86.   {
  87.     *VOL_MV = val;
  88.     return AIO_OK;
  89.   }

  90.   return AIO_ERROR_Param;
  91. }


  92. /**
  93. * @brief  Set analog out voltage collect
  94. *
  95. * @param[in]  AIN_TYPE_OUTx: (AIO_TYPE_OUT_MIN < x < AIO_TYPE_OUT_MAX)
  96. * @param[in]  vol: mv out signal, max 3000mV
  97. *
  98. * @retval 0 Success
  99. */
  100. uint8_t AIO_SetOutVoltage(AIO_TYPE_t AIO_TYPE_OUTx, uint16_t vol)
  101. {
  102.   if ((AIO_TYPE_OUTx <= AIO_TYPE_OUT_MIN) || (AIO_TYPE_OUTx >= AIO_TYPE_OUT_MAX) || vol > 3300)
  103.     return 1;

  104.   if (vol > 3000)
  105.     return 1;

  106.   vol = ((uint32_t)vol * 0xFFFul / 3000ul);

  107.   (void)vol;

  108.   return 0;
  109. }

  110. /**
  111. * @brief Bubble sort sample value
  112. * @param[in] pbuf: data buffer point
  113. * @param[in] len: data buffer length bytes
  114. * @retval None
  115. */
  116. static void aio_sort_bubble(uint16_t *pbuf, uint8_t len)
  117. {
  118.   uint8_t i, j;
  119.   uint16_t temp;

  120.   for (i = 0; i < len - 1; i++)
  121.   {
  122.     for (j = 0; j < len - 1 - i; j++)
  123.     {
  124.       if (pbuf[j] > pbuf[j + 1])
  125.       {
  126.         temp = pbuf[j];
  127.         pbuf[j] = pbuf[j + 1];
  128.         pbuf[j + 1] = temp;
  129.       }
  130.     }
  131.   }
  132. }


  133. /**
  134. * @brief  Sample average value
  135. * @param[in] pbuf: data buffer point
  136. * @param[in] len: data buffer length
  137. * @retval None
  138. */
  139. static uint16_t aio_sample_avg(uint16_t *pbuf, uint8_t len)
  140. {
  141.   uint32_t sum = 0;

  142.   for (uint8_t i = 0; i < len; i++)
  143.     sum += pbuf[i];

  144.   return (sum / len);
  145. }


  146. /**
  147. * @brief  ADC In low level init
  148. * @param  None
  149. * @return None
  150. */
  151. static void AIO_InLowLevelInit(void)
  152. {
  153.   ADC_InitTypeDef       ADC_InitStructure;
  154.   DMA_InitTypeDef       DMA_InitStructure;
  155.   GPIO_InitTypeDef      GPIO_InitStructure;

  156.   // Configure ADC1 Channel pin as analog input
  157.   RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOC, ENABLE);

  158.   GPIO_StructInit(&GPIO_InitStructure);
  159.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
  160.   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;

  161.   for (uint8_t i = 0; i < AIO_CH_NUM_IN; i++)
  162.   {
  163.     GPIO_InitStructure.GPIO_Pin = AIN_PORT_PIN[i].GPIO_Pin;
  164.     GPIO_Init(AIN_PORT_PIN[i].GPIOx, &GPIO_InitStructure);
  165.   }

  166.   // DMA1 channel1 configuration
  167.   lib_memset(s_usAinBuffer, 0, sizeof(s_usAinBuffer));
  168.   RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

  169.   DMA_DeInit(DMA1_Channel1);
  170.   DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
  171.   DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&s_usAinBuffer;
  172.   DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
  173.   DMA_InitStructure.DMA_BufferSize = AIN_BUFF_SIZE * AIO_CH_NUM_IN;
  174.   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  175.   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  176.   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  177.   DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  178.   DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  179.   DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  180.   DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  181.   DMA_Init(DMA1_Channel1, &DMA_InitStructure);

  182.   // Enable Transfer Complete interrupt
  183.   DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);

  184.   //DMA_SetCurrDataCounter(DMA1_Channel1, 0);
  185.   DMA_Cmd(DMA1_Channel1, ENABLE);

  186.   // Enable the HSI oscillator
  187.   //RCC_HSICmd(ENABLE);

  188.   // Check that HSI oscillator is ready
  189.   //while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);

  190.   // ADC clock
  191.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);

  192.   // ADC Init
  193.   ADC_DeInit(ADC1);
  194.   ADC_StructInit(&ADC_InitStructure);
  195.   ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
  196.   ADC_InitStructure.ADC_ScanConvMode = ENABLE;
  197.   ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
  198.   ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
  199.   ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  200.   ADC_InitStructure.ADC_NbrOfConversion = AIO_CH_NUM_IN;
  201.   ADC_Init(ADC1, &ADC_InitStructure);

  202.   // ADC regular channel configuration
  203.   // ADC_IN10,11,12,13
  204.   // ADC_IN4,5,6,7
  205.   ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_4Cycles);
  206.   ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_4Cycles);
  207.   ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 3, ADC_SampleTime_4Cycles);
  208.   ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 4, ADC_SampleTime_4Cycles);

  209.   ADC_RegularChannelConfig(ADC1, ADC_Channel_4,  5, ADC_SampleTime_4Cycles);
  210.   ADC_RegularChannelConfig(ADC1, ADC_Channel_5,  6, ADC_SampleTime_4Cycles);
  211.   ADC_RegularChannelConfig(ADC1, ADC_Channel_6,  7, ADC_SampleTime_4Cycles);
  212.   ADC_RegularChannelConfig(ADC1, ADC_Channel_7,  8, ADC_SampleTime_4Cycles);

  213.   //ADC_RegularChannelConfig(ADC1, ADC_Channel_Vrefint, 9, ADC_SampleTime_16Cycles);
  214.   //ADC_TempSensorVrefintCmd(ENABLE);

  215.   // Enable the request after last transfer for DMA Circular mode
  216.   ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);

  217.   // Enable ADC DMA
  218.   ADC_DMACmd(ADC1, ENABLE);

  219.   // Enable ADC
  220.   ADC_Cmd(ADC1, ENABLE);

  221.   // Wait until the ADC1 is ready
  222.   while(ADC_GetFlagStatus(ADC1, ADC_FLAG_ADONS) == RESET);

  223.   // Start ADC Software Conversion
  224.   ADC_SoftwareStartConv(ADC1);
  225. }

  226. /**
  227. * @brief  ADC Out low level init
  228. * @param  None
  229. * @return None
  230. */
  231. static void AIO_OutLowLevelInit(void)
  232. {
  233. }


  234. /**
  235.   * @brief  This function handles DMA1 Channel 1 interrupt request.
  236.   * @param  None
  237.   * @retval None
  238.   */
  239. void DMA1_Channel1_IRQHandler(void)
  240. {
  241.   // DMA1 Channel1 Transfer Complete
  242.   if(DMA_GetITStatus(DMA1_IT_TC1))
  243.   {
  244.     ADC_Cmd(ADC1, DISABLE);
  245.     ADC_DMACmd(ADC1, DISABLE);
  246.     DMA_Cmd(DMA1_Channel1, DISABLE);

  247.     // Clear DMA1 Channel1 interrupt pending bits
  248.     DMA_ClearITPendingBit(DMA1_IT_GL1);
  249.   }
  250. }


  251. /**
  252. * @}
  253. */
复制代码

出100入143汤圆

发表于 2020-4-17 21:46:31 | 显示全部楼层
  1. /* Define to prevent recursive inclusion -------------------------------------*/
  2. #ifndef __ANALOGIO_H
  3. #define __ANALOGIO_H

  4. #ifdef __cplusplus
  5. extern "C" {
  6. #endif  /* __cplusplus */

  7. /* INCLUDES ----------------------------------------------------------------- */
  8. #include <stdint.h>

  9. /**
  10. * @addtogroup AnalogIO
  11. * @{
  12. */

  13. /* TYPEDEFS ----------------------------------------------------------------- */

  14. /**
  15. * @brief Analog in and out error status
  16. */
  17. typedef enum
  18. {
  19.   AIO_OK = 0,
  20.   AIO_ERROR_Param,
  21. }AIO_ERROR_t;


  22. /**
  23. * @brief Analog in channel type
  24. */
  25. typedef enum
  26. {
  27.   AIO_TYPE_IN_MIN,    /*!< Analog input */
  28.   AIO_TYPE_IN1,
  29.   AIO_TYPE_IN2,
  30.   AIO_TYPE_IN3,
  31.   AIO_TYPE_IN4,
  32.   AIO_TYPE_IN5,
  33.   AIO_TYPE_IN6,
  34.   AIO_TYPE_IN7,
  35.   AIO_TYPE_IN8,
  36.   AIO_TYPE_IN_MAX,

  37.   AIO_TYPE_OUT_MIN,    /*!< Analog output */
  38.   AIO_TYPE_OUT_MAX
  39. }AIO_TYPE_t;

  40. /* MACROS  ------------------------------------------------------------------ */

  41. /* CONSTANTS  --------------------------------------------------------------- */

  42. #define AIO_CH_NUM_IN  (AIO_TYPE_IN_MAX - AIO_TYPE_IN_MIN - 1)
  43. #define AIO_CH_NUM_OUT  (AIO_TYPE_OUT_MAX - AIO_TYPE_OUT_MIN - 1)

  44. /* GLOBAL VARIABLES --------------------------------------------------------- */

  45. /* GLOBAL FUNCTIONS --------------------------------------------------------- */

  46. AIO_ERROR_t AIO_Init(void);
  47. void        AIO_SetInStatus(uint8_t status);

  48. AIO_ERROR_t AIO_GetInVoltage(AIO_TYPE_t AIO_TYPE_INx, uint16_t *VOL_MV);

  49. /* LOCAL VARIABLES ---------------------------------------------------------- */

  50. /* LOCAL FUNCTIONS ---------------------------------------------------------- */


  51. #ifdef __cplusplus
  52. }
  53. #endif  /* __cplusplus */

  54. #endif /* __ANALOGIO_H */

  55. /**
  56. * @}
  57. */

  58. /***************************** END OF FILE ***************
复制代码

出100入143汤圆

发表于 2020-4-17 21:46:58 | 显示全部楼层
本帖最后由 zzh90513 于 2020-4-17 21:48 编辑

STM32L151RE,读取数据已带冒泡排序和取中间求平均

出0入79汤圆

发表于 2020-4-17 22:14:10 | 显示全部楼层
zzh90513 发表于 2020-4-17 21:46
STM32L151RE,读取数据已带冒泡排序和取中间求平均

挺你一下,赞!

出0入0汤圆

 楼主| 发表于 2020-4-18 00:08:12 | 显示全部楼层
zzh90513 发表于 2020-4-17 21:46
STM32L151RE,读取数据已带冒泡排序和取中间求平均

感谢!
对了,初始化第一次有总断,后面就没有总断,也就是AD没有一直采样,如何才能让AD一直采样!谢谢

出100入143汤圆

发表于 2020-4-18 08:59:48 | 显示全部楼层
zhouyan 发表于 2020-4-18 00:08
感谢!
对了,初始化第一次有总断,后面就没有总断,也就是AD没有一直采样,如何才能让AD一直采样!谢谢 ...

你看一遍程序就明白了,我这个是间歇性采样,在DMA完成中断里面把采样关了,你屏蔽掉就行,甚至如果你是连续采样,可以DMA中断关了,直接获取模拟值,buffer里面的采样值是自动循环刷新的

出0入0汤圆

发表于 2020-4-18 10:44:56 | 显示全部楼层
日后学习用,mark

出0入0汤圆

发表于 2020-4-28 16:38:35 | 显示全部楼层
学习了

出0入53汤圆

发表于 2020-11-7 11:30:32 | 显示全部楼层
zzh90513 发表于 2020-4-17 21:46
STM32L151RE,读取数据已带冒泡排序和取中间求平均

L151使用HSI->pll  得到系统32M  有设置代码吗

我直接操作寄存器,一设置就死掉了
RCC->CR |= 0X3;
        RCC->CFGR |= 0X440000;
        RCC->CR |= RCC_CR_PLLON;
        RCC->CFGR |= RCC_CFGR_SW;
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-24 00:34

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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