OpenEdv-开源电子网

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

HAL库版定时器+ADC+DMA实现多通道AD采集

[复制链接]

27

主题

89

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1382
金钱
1382
注册时间
2017-9-5
在线时间
151 小时
发表于 2018-6-17 02:38:48 | 显示全部楼层 |阅读模式
ADC部分源码:
[mw_shl_code=c,true]u16 advalue[7200];                                                                                                                //buff
ADC_HandleTypeDef ADC1_Handler;                                                                                        //ADC句柄

void ADC_GPIO_Config(void)                                                                //GPIO配置
{
        GPIO_InitTypeDef GPIO_Initure;
    __HAL_RCC_ADC1_CLK_ENABLE();                                                                    //使能ADC1时钟
    __HAL_RCC_GPIOA_CLK_ENABLE();                                                                                //开启GPIOA时钟
       
    GPIO_Initure.Pin=GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;                                        //PA1
    GPIO_Initure.Mode=GPIO_MODE_ANALOG;                                                             //模拟
    GPIO_Initure.Pull=GPIO_NOPULL;                                                                  //不带上下拉
    HAL_GPIO_Init(GPIOA,&GPIO_Initure);
}

static void ADC_Config(void)                                                        //ADC配置
{      
    ADC1_Handler.Instance=ADC1;                                                                                        //ADC1
    ADC1_Handler.Init.DataAlign=ADC_DATAALIGN_RIGHT;                             //右对齐
    ADC1_Handler.Init.ScanConvMode=ENABLE;                                      //非扫描模式
    ADC1_Handler.Init.ContinuousConvMode=DISABLE;                                //关闭连续转换
    ADC1_Handler.Init.NbrOfConversion=3;                                         //1个转换在规则序列中 也就是只转换规则序列1
    ADC1_Handler.Init.DiscontinuousConvMode=DISABLE;                             //禁止不连续采样模式
    ADC1_Handler.Init.NbrOfDiscConversion=0;                                     //不连续采样通道数为0
    ADC1_Handler.Init.ExternalTrigConv=ADC_EXTERNALTRIGCONV_T3_TRGO;         //定时器3触发
    HAL_ADC_Init(&ADC1_Handler);                                                 //初始化
  
        HAL_ADCEx_Calibration_Start(&ADC1_Handler);                                                         //校准ADC
        // ADC_RegularChannelConfig 为自己写的一个函数
    ADC_RegularChannelConfig(&ADC1_Handler, ADC_CHANNEL_1, 1, ADC_SAMPLETIME_55CYCLES_5);
    ADC_RegularChannelConfig(&ADC1_Handler, ADC_CHANNEL_2, 2, ADC_SAMPLETIME_55CYCLES_5);
    ADC_RegularChannelConfig(&ADC1_Handler, ADC_CHANNEL_3, 3, ADC_SAMPLETIME_55CYCLES_5);
        
    ADC_DMA_Cfg();                                                                                                                //DMA配置   
    HAL_ADC_Start_DMA(&ADC1_Handler, (uint32_t*)&advalue,12);                        //开始DMA
}


//ADC转换通道
static void ADC_RegularChannelConfig(ADC_HandleTypeDef *AdcHandle, uint32_t Channel, uint32_t Rank, uint32_t SamplingTime)
{
    ADC_ChannelConfTypeDef ADC1_ChanConf;      
        
    ADC1_ChanConf.Channel      = Channel;                                                                //通道
    ADC1_ChanConf.Rank         = Rank;                                                                        //第几个序列
    ADC1_ChanConf.SamplingTime = SamplingTime;                                                        //采样时间

    HAL_ADC_ConfigChannel(AdcHandle,&ADC1_ChanConf);                                        //通道配置
}


void ADC_Init(void)                        //整体初始化
{
    ADC_GPIO_Config();                        //GPIO配置
    ADC_Config();                                //AD配置
        Adc_Timer_Init();                        //定时器3初始化
}
[/mw_shl_code]
定时器部分源码:
[mw_shl_code=c,true]TIM_HandleTypeDef TIM3_Handler;      //定时器句柄

//通用定时器3中断初始化
//arr:自动重装值
//psc:时钟预分频数
//定时器溢出时间计算方法:Tout=((arr+1)*(psc+1))/Ft us.
//Ft=定时器工作频率,单位:Mhz
//这里使用的是定时器3!  定时器溢出时间为 500ms
void Adc_Timer_Init(void)                        //定时器3初始化
{
        TIM3_Handler.Instance=TIM3;                                  //通用定时器3
    TIM3_Handler.Init.Prescaler=7200-1;                     //分频系数
    TIM3_Handler.Init.CounterMode=TIM_COUNTERMODE_UP;            //向上计数器
    TIM3_Handler.Init.Period=5000-1;                        //自动装载值
    TIM3_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;        //时钟分频因子
        HAL_TIM_Base_DeInit(&TIM3_Handler);                                                //时基复位
    HAL_TIM_Base_Init(&TIM3_Handler);                                                                       
   
    HAL_TIM_Base_Start_IT(&TIM3_Handler);                                         //使能定时器3和定时器3更新中断:TIM_IT_UPDATE
}

//定时器底册驱动,开启时钟,设置中断优先级
//此函数会被HAL_TIM_Base_Init()函数调用
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{
    if(htim->Instance==TIM3)
        {
                __HAL_RCC_TIM3_CLK_ENABLE();                                    //使能TIM3时钟
                HAL_NVIC_SetPriority(TIM3_IRQn,1,3);                            //设置中断优先级,抢占优先级1,子优先级3
                HAL_NVIC_EnableIRQ(TIM3_IRQn);                                  //开启ITM3中断   
        }
}

//定时器3中断服务函数
void TIM3_IRQHandler(void)
{
    HAL_TIM_IRQHandler(&TIM3_Handler);
}

//回调函数,定时器中断服务函数调用
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(htim==(&TIM3_Handler))
    {
        HAL_ADC_Start(&ADC1_Handler);                                                //开启AD转换
    }
}
[/mw_shl_code]
DMA部分源码:
[mw_shl_code=c,true]extern u16 advalue[7200];
DMA_HandleTypeDef  ADC1rxDMA_Handler;                                                                      //DMA句柄

//DMA1的各通道配置
//这里的传输形式是固定的,这点要根据不同的情况来修改
//从存储器->外设模式/8位数据宽度/存储器增量模式

void ADC_DMA_Cfg(void)                                                //DMA配置
{
    __HAL_RCC_DMA1_CLK_ENABLE();                                                                                //DMA1时钟使能

    ADC1rxDMA_Handler.Instance = DMA1_Channel1;                                                        //DMA通道选择
    ADC1rxDMA_Handler.Init.Direction=DMA_PERIPH_TO_MEMORY;                     //外设到存储器
    ADC1rxDMA_Handler.Init.PeriphInc=DMA_PINC_DISABLE;                        //外设非增量模式
    ADC1rxDMA_Handler.Init.MemInc=DMA_MINC_ENABLE;                             //存储器增量模式
    ADC1rxDMA_Handler.Init.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD;        //外设数据长度:16位
    ADC1rxDMA_Handler.Init.MemDataAlignment=DMA_MDATAALIGN_HALFWORD;          //存储器数据长度:16位
    ADC1rxDMA_Handler.Init.Mode=DMA_CIRCULAR;                                 //外设循环模式
    ADC1rxDMA_Handler.Init.Priority=DMA_PRIORITY_HIGH;                       //中等优先级

        ADC1rxDMA_Handler.XferCpltCallback = HAL_DMA_IRQHandler;
       
    HAL_DMA_DeInit(&ADC1rxDMA_Handler);                                                                   //DMA复位
    HAL_DMA_Init(&ADC1rxDMA_Handler);                                                                        //DMA初始化
       
        __HAL_LINKDMA(&ADC1_Handler,DMA_Handle,ADC1rxDMA_Handler);                    //将DMA与ADC联系起来(发送DMA)
       
    HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 1, 1);                                                //DMA中断优先级
    HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);                                                                //使能DMA中断
       
}

// DMA通道1中断服务函数 (完成中断)
void DMA1_Channel1_IRQHandler(void)
{
        HAL_DMA_IRQHandler(&ADC1rxDMA_Handler);
        printf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\r\n",advalue[0],advalue[1],advalue[2],advalue[3],advalue[4],advalue[5],advalue[6],advalue[7],advalue[8],advalue[9],advalue[10],advalue[11]);       
}[/mw_shl_code]
仅供参考

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

使用道具 举报

2

主题

10

帖子

0

精华

新手上路

积分
44
金钱
44
注册时间
2018-7-6
在线时间
7 小时
发表于 2018-7-18 09:52:45 | 显示全部楼层
大哥代码不全啊, 能否上传个源代码
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
3
金钱
3
注册时间
2018-8-8
在线时间
0 小时
发表于 2018-8-8 17:04:39 | 显示全部楼层
太好了,你帮我解决了一个大问题,谢谢
回复 支持 反对

使用道具 举报

27

主题

89

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1382
金钱
1382
注册时间
2017-9-5
在线时间
151 小时
 楼主| 发表于 2018-8-9 10:56:29 | 显示全部楼层
w744923181 发表于 2018-8-8 17:04
太好了,你帮我解决了一个大问题,谢谢

客气啦,应该的
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手上路

积分
36
金钱
36
注册时间
2018-8-11
在线时间
5 小时
发表于 2018-8-13 12:58:28 | 显示全部楼层
顶一个
回复 支持 反对

使用道具 举报

3

主题

12

帖子

0

精华

新手上路

积分
45
金钱
45
注册时间
2018-10-10
在线时间
8 小时
发表于 2018-10-10 09:25:18 | 显示全部楼层
请问一下大佬,那个ADC配置的时候采用定时器3触发和直接再定时器中断中开启AD采样有什么差别吗,还有大佬你这样采用三个通道采样那么dma发送数据给数组的时候是怎么发的数据呀
回复 支持 反对

使用道具 举报

4

主题

22

帖子

0

精华

初级会员

Rank: 2

积分
57
金钱
57
注册时间
2019-11-21
在线时间
10 小时
发表于 2020-3-23 15:55:32 | 显示全部楼层
大哥啊   我想知道 ADC_RegularChannelConfig(&ADC1_Handler, ADC_CHANNEL_1, 1, ADC_SAMPLETIME_55CYCLES_5);这个函数是哪的
回复 支持 反对

使用道具 举报

4

主题

178

帖子

0

精华

高级会员

Rank: 4

积分
672
金钱
672
注册时间
2019-7-28
在线时间
61 小时
发表于 2020-4-9 17:09:33 | 显示全部楼层
请问:
HAL库里对应的:ADC_RegularChannelConfig函数这么实现的
回复 支持 反对

使用道具 举报

0

主题

12

帖子

0

精华

初级会员

Rank: 2

积分
127
金钱
127
注册时间
2020-1-11
在线时间
21 小时
发表于 2020-5-4 15:13:36 | 显示全部楼层
66666666666666666666666666
回复 支持 反对

使用道具 举报

0

主题

4

帖子

0

精华

新手上路

积分
20
金钱
20
注册时间
2019-11-17
在线时间
3 小时
发表于 2020-8-20 09:58:32 | 显示全部楼层
失落的小孩 发表于 2020-3-23 15:55
大哥啊   我想知道 ADC_RegularChannelConfig(&ADC1_Handler, ADC_CHANNEL_1, 1, ADC_SAMPLETIME_55CYCLES_ ...

HAL库自带函数
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-14 12:28

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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