|

楼主 |
发表于 2024-11-20 23:11:48
|
显示全部楼层
对应代码如下:
[C] 纯文本查看 复制代码
初始化
ADC_dev adc1 = {
.adc = ADC1,
.ch[0] = ADC_CH16,
.ch[1] = ADC_CH17,
.ch_num = 2,
.buf.data = adc1_buf,
.buf.len = sizeof(adc1_buf)/2,
};
ADC_dev adc2 = {
.adc = ADC2,
.ch[0] = ADC_CH3,
.ch[1] = ADC_CH4,
.ch_num = 2,
.buf.data = adc2_buf,
.buf.len = sizeof(adc2_buf)/2,
};
ADC_dev adc3 = {
.adc = ADC3,
.ch[0] = ADC_CH0,
.ch[1] = ADC_CH1,
.ch_num = 2,
.buf.data = adc3_buf,
.buf.len = sizeof(adc3_buf)/2,
};
ADC_Init(&adc1);
ADC_Init(&adc2);
ADC_Init(&adc3);
ADC_InitTimer(&adc1,500);
ADC_InitTimer(&adc2,500);
ADC_InitTimer(&adc3,500);
获取数据
SCB_InvalidateDCache_by_Addr((uint32_t *)(obj->cur.ch1.adc->buf.data),obj->cur.ch1.adc->buf.len*4 + 32);
SCB_InvalidateDCache_by_Addr((uint32_t *)(obj->cur.ch3.adc->buf.data),obj->cur.ch3.adc->buf.len*4 + 32);
SCB_InvalidateDCache_by_Addr((uint32_t *)(obj->tmp.adc->buf.data),obj->tmp.adc->buf.len*4 + 32);
for (int i = 0; i < ADC_BUF_LEN; i=i+2)
{
UART_Printf(WAVE_UART,"%f,%f,%f,%f,%f,%f,%f\n",(float)i,
(float)obj->cur.ch1.adc->buf.data[i],
(float)obj->cur.ch1.adc->buf.data[i+1],
(float)obj->cur.ch3.adc->buf.data[i],
(float)obj->cur.ch3.adc->buf.data[i+1],
(float)obj->tmp.adc->buf.data[i],
(float)obj->tmp.adc->buf.data[i+1]
);
}
ADC.C
[C] 纯文本查看 复制代码 /*******************************************************************************
Header Files 头文件
*******************************************************************************/
#include "bsp.h"
#include "adc.h"
/*******************************************************************************
Macro Definition 宏定义
*******************************************************************************/
/*******************************************************************************
Variable declarations 变量声明
*******************************************************************************/
//ADC通道
uint32_t AdcCh[] = {
ADC_CHANNEL_0 , ADC_CHANNEL_1 , ADC_CHANNEL_2 , ADC_CHANNEL_3 , ADC_CHANNEL_4 ,
ADC_CHANNEL_5 , ADC_CHANNEL_6 , ADC_CHANNEL_7 , ADC_CHANNEL_8 , ADC_CHANNEL_9 ,
ADC_CHANNEL_10, ADC_CHANNEL_11, ADC_CHANNEL_12, ADC_CHANNEL_13, ADC_CHANNEL_14,
ADC_CHANNEL_15, ADC_CHANNEL_16, ADC_CHANNEL_17, ADC_CHANNEL_18, ADC_CHANNEL_19
};
//ADC 采样优先级
uint32_t ADCRank[] = {
ADC_REGULAR_RANK_1 , ADC_REGULAR_RANK_2 , ADC_REGULAR_RANK_3 , ADC_REGULAR_RANK_4 ,
ADC_REGULAR_RANK_5 , ADC_REGULAR_RANK_6 , ADC_REGULAR_RANK_7 , ADC_REGULAR_RANK_8 ,
ADC_REGULAR_RANK_9 , ADC_REGULAR_RANK_10, ADC_REGULAR_RANK_11, ADC_REGULAR_RANK_12,
ADC_REGULAR_RANK_13, ADC_REGULAR_RANK_14, ADC_REGULAR_RANK_15, ADC_REGULAR_RANK_16
};
//ADC1管脚
GPIO_TypeDef * ADC1Gpio[] = {
GPIOA, GPIOA, GPIOF, GPIOA, GPIOC, GPIOB, GPIOF, GPIOA, GPIOC, GPIOB,
GPIOC, GPIOC, GPIOC, GPIOC, GPIOA, GPIOA, GPIOA, GPIOA, GPIOA, GPIOA
};
uint16_t ADC1Pin[] = {
GPIO_PIN_0, GPIO_PIN_1, GPIO_PIN_11, GPIO_PIN_6, GPIO_PIN_4, GPIO_PIN_1, GPIO_PIN_12, GPIO_PIN_7, GPIO_PIN_5, GPIO_PIN_0,
GPIO_PIN_0, GPIO_PIN_1, GPIO_PIN_2 , GPIO_PIN_3, GPIO_PIN_2, GPIO_PIN_3, GPIO_PIN_0 , GPIO_PIN_1, GPIO_PIN_4, GPIO_PIN_5
};
//ADC2管脚
GPIO_TypeDef * ADC2Gpio[] = {
GPIOA, GPIOA, GPIOF, GPIOA, GPIOC, GPIOB, GPIOF, GPIOA, GPIOC, GPIOB,
GPIOC, GPIOC, GPIOC, GPIOC, GPIOA, GPIOA, NULL , NULL , GPIOA, GPIOA
};
uint16_t ADC2Pin[] = {
GPIO_PIN_0, GPIO_PIN_1, GPIO_PIN_13, GPIO_PIN_6, GPIO_PIN_4, GPIO_PIN_1, GPIO_PIN_14, GPIO_PIN_7, GPIO_PIN_5, GPIO_PIN_0,
GPIO_PIN_0, GPIO_PIN_1, GPIO_PIN_2 , GPIO_PIN_3, GPIO_PIN_2, GPIO_PIN_3, NULL , NULL , GPIO_PIN_4, GPIO_PIN_5
};
//ADC3管脚
GPIO_TypeDef * ADC3Gpio[] = {
GPIOC, GPIOC, GPIOF, GPIOF, GPIOF, GPIOF, GPIOF, GPIOF, GPIOF, GPIOF,
GPIOC, GPIOC, GPIOC, GPIOH, GPIOH, GPIOH, GPIOH, NULL , NULL , NULL
};
uint16_t ADC3Pin[] = {
GPIO_PIN_2, GPIO_PIN_3, GPIO_PIN_9, GPIO_PIN_7, GPIO_PIN_5, GPIO_PIN_3, GPIO_PIN_10, GPIO_PIN_8, GPIO_PIN_6, GPIO_PIN_4,
GPIO_PIN_8, GPIO_PIN_1, GPIO_PIN_2, GPIO_PIN_2, GPIO_PIN_3, GPIO_PIN_4, GPIO_PIN_5 , NULL , NULL , NULL
};
TIM_HandleTypeDef gTimer;
/** ****************************************************************************
* @brief 初始化adc的gpio
* @param dev 设备对象
*******************************************************************************/
static uint32_t ADC_IoInit(ADC_dev* dev, uint8_t idx)
{
if(dev->adc == ADC1)
{
GPIO_Init(ADC1Gpio[idx], ADC1Pin[idx], GPIO_AN_PN_L);
}
else if(dev->adc == ADC2)
{
GPIO_Init(ADC2Gpio[idx], ADC2Pin[idx], GPIO_AN_PN_L);
}
else if (dev->adc == ADC3)
{
GPIO_Init(ADC3Gpio[idx], ADC3Pin[idx], GPIO_AN_PN_L);
}
return ADC_OK;
}
/** ****************************************************************************
* @brief 获取adc当前count
*******************************************************************************/
uint32_t ADC_GetCount(ADC_dev *dev)
{
uint32_t idx;
idx = dev->buf.len - __HAL_DMA_GET_COUNTER(&dev->hdma_adc);
return idx;
}
/** ****************************************************************************
* @brief 获取通道采样结果
*******************************************************************************/
void ADC_GetChVal(ADC_dev* dev, uint32_t* buf, uint32_t len, uint32_t ch)
{
uint32_t idx1, idx2,rank,buflen;
uint8_t i;
buflen = dev->buf.len - (dev->buf.len % dev->ch_num);
idx1 = ADC_GetCount(dev);
idx2 = (buflen + idx1 - len * dev->ch_num) - 1; //多减1防止拿到DMA推送不全的数据
for(i = 0; i < dev->ch_num; i++)
{
if(dev->ch[i] == AdcCh[ch])
break;
}
rank = i;
while(idx2 % dev->ch_num != rank) idx2--;
SCB_InvalidateDCache_by_Addr((uint32_t *)dev->buf.data,dev->buf.len *4 +32);
for(uint32_t i=0; i < len;i++)
{
idx2 = idx2 % buflen;
buf[i] = dev->buf.data[idx2];
idx2 += dev->ch_num;
}
}
/** ****************************************************************************
* @brief ADC初始化
* @param dev ADC对象
*******************************************************************************/
int ADC_InitDma(ADC_dev* dev)
{
if(dev->adc == ADC1)
{
__HAL_RCC_DMA1_CLK_ENABLE();
dev->hdma_adc.Instance = DMA1_Stream0;
dev->hdma_adc.Init.Request = DMA_REQUEST_ADC1;
}
else if(dev->adc == ADC2)
{
__HAL_RCC_DMA1_CLK_ENABLE();
dev->hdma_adc.Instance = DMA1_Stream1;
dev->hdma_adc.Init.Request = DMA_REQUEST_ADC2;
}
else if(dev->adc == ADC3)
{
__HAL_RCC_BDMA_CLK_ENABLE();
dev->hdma_adc.Instance = BDMA_Channel0;
dev->hdma_adc.Init.Request = BDMA_REQUEST_ADC3;
}
dev->hdma_adc.Init.Direction = DMA_PERIPH_TO_MEMORY; //外设到内存
dev->hdma_adc.Init.PeriphInc = DMA_PINC_DISABLE; //外设地址不递增
dev->hdma_adc.Init.MemInc = DMA_MINC_ENABLE; //内存地址递增
dev->hdma_adc.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; //外设数据宽度:字节
dev->hdma_adc.Init.MemDataAlignment = DMA_PDATAALIGN_HALFWORD; //内存数据宽度:字节
dev->hdma_adc.Init.Mode = DMA_CIRCULAR; //传输模式(循环)
dev->hdma_adc.Init.Priority = DMA_PRIORITY_MEDIUM; //优先级
dev->hdma_adc.Init.FIFOMode = DMA_FIFOMODE_DISABLE; //禁用fifo
if (HAL_DMA_Init(&dev->hdma_adc) != HAL_OK)
{
ADC_ERR("ADC DMA init err!");
return ADC_INIT_DMA_ERR;
}
__HAL_LINKDMA(&dev->hadc,DMA_Handle,dev->hdma_adc);
return ADC_OK;
}
/** ****************************************************************************
* @brief ADC通道初始化
* @param dev ADC对象
* @param ch ADC通道
* @param rank 采样顺序
*******************************************************************************/
int ADC_InitCh(ADC_dev* dev,uint8_t ch,uint32_t rank)
{
ADC_ChannelConfTypeDef sConfig = {0};
ADC_IoInit(dev,ch);
sConfig.Channel = AdcCh[ch]; //采样通道
sConfig.Rank = rank; //规则通道,即采样顺序
sConfig.SamplingTime = ADC_SAMPLETIME_8CYCLES_5; //采样时间
sConfig.SingleDiff = ADC_SINGLE_ENDED; //单端采样
sConfig.OffsetNumber = ADC_OFFSET_NONE; //偏移校准
sConfig.Offset = 0;
if (HAL_ADC_ConfigChannel(&dev->hadc, &sConfig) != HAL_OK)
{
ADC_ERR("ADC CH init err!");
return ADC_INIT_CH_ERR;
}
return ADC_OK;
}
/** ****************************************************************************
* @brief 初始化ADC
*******************************************************************************/
int ADC_Init(ADC_dev* dev)
{
RCC_PeriphCLKInitTypeDef RCC_PeriphClkInit;
ADC_MultiModeTypeDef multimode = {0};
uint16_t pll2m,pll2n,PLL2P;
//根据外部晶振选择分频系数
switch (HSE_VALUE)
{
case 25000000 : pll2m = 5;pll2n = 72;PLL2P = 10; break;
case 24000000 : pll2m = 4;pll2n = 60;PLL2P = 10; break;
case 8000000 : pll2m = 1;pll2n = 45;PLL2P = 10; break;
default: return -1;
}
//ADC设置为最高频率36MHz
RCC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC; //外设时钟
RCC_PeriphClkInit.AdcClockSelection = RCC_ADCCLKSOURCE_PLL2; //ADC时钟
RCC_PeriphClkInit.PLL2.PLL2FRACN = 0;
RCC_PeriphClkInit.PLL2.PLL2M = pll2m;
RCC_PeriphClkInit.PLL2.PLL2N = pll2n;
RCC_PeriphClkInit.PLL2.PLL2P = PLL2P;
RCC_PeriphClkInit.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_2;
RCC_PeriphClkInit.PLL2.PLL2VCOSEL = RCC_PLL2VCOWIDE;
HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit);
//配置ADC
HAL_ADC_DeInit(&(dev->hadc));
if(dev->adc == ADC2)
{
__HAL_RCC_ADC12_CLK_ENABLE();
dev->hadc.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T1_CC1; //触发源
}
else if(dev->adc == ADC1)
{
__HAL_RCC_ADC12_CLK_ENABLE();
dev->hadc.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T1_CC2; //触发源
}
else
{
__HAL_RCC_ADC3_CLK_ENABLE();
dev->hadc.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T1_CC3; //触发源
}
dev->hadc.Instance = dev->adc;
dev->hadc.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR; //采样结果通过DMA传输到指定地址
dev->hadc.Init.DiscontinuousConvMode = DISABLE; //禁用不连续采样模式
dev->hadc.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1; //ADC时钟不分频
dev->hadc.Init.Resolution = ADC_RESOLUTION_16B; //16位采样模式
dev->hadc.Init.ScanConvMode = ((dev->ch_num < 2) ? ADC_SCAN_DISABLE : ADC_SCAN_ENABLE); //扫描模式(多通道模式)
dev->hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV; //转换结束标识(序列转换结束)
dev->hadc.Init.LowPowerAutoWait = DISABLE; //禁用低功耗等待模式
dev->hadc.Init.ContinuousConvMode = DISABLE; //禁用连续采样模式(由定时器单次触发)
dev->hadc.Init.NbrOfConversion = dev->ch_num; //规则采样通道数
dev->hadc.Init.NbrOfDiscConversion = 1; //采样组数量
dev->hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING; //触发类型
dev->hadc.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN; //数据溢出处理方式(覆盖写入)
dev->hadc.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE; //ADC转换结果左移位数
dev->hadc.Init.OversamplingMode = DISABLE; //使能过采样
dev->hadc.Init.Oversampling.Ratio = 16; //16x过采样
dev->hadc.Init.Oversampling.RightBitShift = ADC_RIGHTBITSHIFT_4; //采样结果/16获得平均值
dev->hadc.Init.Oversampling.TriggeredMode = ADC_TRIGGEREDMODE_SINGLE_TRIGGER; //触发模式(单次触发)
dev->hadc.Init.Oversampling.OversamplingStopReset = ADC_REGOVERSAMPLING_RESUMED_MODE; //过采样被中断的处理方案(保持缓冲区)
if (HAL_ADC_Init(&(dev->hadc)) != HAL_OK)
{
ADC_DBUG("ADC Init error!");
return ADC_INIT_ERR;
}
//配置ADC通道
for(int i=0;i<dev->ch_num;i++)
{
ADC_InitCh(dev,dev->ch[i],ADCRank[i]);
}
//启动ADC
if (HAL_ADCEx_Calibration_Start(&dev->hadc,ADC_CALIB_OFFSET, ADC_SINGLE_ENDED) != HAL_OK)
{
ADC_ERR("ADC adj err!");
return ADC_INIT_ERR;
}
//设置DMA
ADC_InitDma(dev);
//DMA启动后续进一步设置定时器才会真正开始采样
HAL_ADC_Start_DMA(&dev->hadc,(uint32_t*)dev->buf.data,dev->buf.len);
return ADC_OK;
}
/** ****************************************************************************
* @brief 初始化adc的定时器
* @Freq 采样频率(Hz)
*******************************************************************************/
int ADC_InitTimer(ADC_dev* dev,uint32_t Freq)
{
TIM_OC_InitTypeDef sConfig = {0};
RCC_ClkInitTypeDef fclk = {0};
uint32_t latency; //flash延迟,仅用于满足函数接口,本函数用不上
uint32_t clk = 0;
uint32_t div = 0;
uint16_t Period;
if(dev->adc == ADC2)
{
__HAL_RCC_TIM1_CLK_ENABLE();
gTimer.Instance = TIM1;
}
else if(dev->adc == ADC1)
{
__HAL_RCC_TIM1_CLK_ENABLE();
gTimer.Instance = TIM1;
}
else
{
__HAL_RCC_TIM1_CLK_ENABLE();
gTimer.Instance = TIM1;
}
HAL_RCC_GetClockConfig(&fclk, &latency);
clk = HAL_RCC_GetPCLK1Freq() *(fclk.APB1CLKDivider== RCC_HCLK_DIV1 ? 1 : 2);
//计算定时器分频和重载计数
div = (clk / ((0xFFFF-1U) * Freq)) +1;
Period = ((clk / (div * Freq)) - 1);
gTimer.Init.Period = Period;
gTimer.Init.Prescaler = div-1;
gTimer.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
gTimer.Init.CounterMode = TIM_COUNTERMODE_UP;
gTimer.Init.RepetitionCounter = 0x0; //重复计数器,每次溢出-1,至0时触发定时事件
gTimer.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; //自动重载模式(立刻生效)
if (HAL_TIM_PWM_Init(&gTimer) != HAL_OK)
{
ADC_ERR("ADC timer init err!");
return ADC_INIT_TIMER_ERR;
}
/* 配置定时器PWM输出通道 */
sConfig.OCMode = TIM_OCMODE_PWM1;
sConfig.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfig.OCFastMode = TIM_OCFAST_DISABLE;
sConfig.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfig.OCNIdleState = TIM_OCNIDLESTATE_RESET;
sConfig.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfig.Pulse = Period; // 50%占空比
if(dev->adc == ADC2)
{
HAL_TIM_PWM_ConfigChannel(&gTimer, &sConfig, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&gTimer, TIM_CHANNEL_1);
}
else if(dev->adc == ADC1)
{
HAL_TIM_PWM_ConfigChannel(&gTimer, &sConfig, TIM_CHANNEL_2);
HAL_TIM_PWM_Start(&gTimer, TIM_CHANNEL_2);
}
else
{
HAL_TIM_PWM_ConfigChannel(&gTimer, &sConfig, TIM_CHANNEL_3);
HAL_TIM_PWM_Start(&gTimer, TIM_CHANNEL_3);
}
return ADC_OK;
}
/** ****************************************************************************
* @brief ADC停止采样
*******************************************************************************/
void ADC_Stop(void)
{
HAL_TIM_PWM_Stop(&gTimer,TIM_CHANNEL_1);
}
/** ****************************************************************************
* @brief ADC开始采样
*******************************************************************************/
void ADC_Start(void)
{
HAL_TIM_PWM_Start(&gTimer,TIM_CHANNEL_1);
}
ADC.h
[C] 纯文本查看 复制代码 #ifndef __ADC_H
#define __ADC_H
/*******************************************************************************
Header Files 头文件
*******************************************************************************/
#include <stdio.h>
#include "ctype.h"
/*******************************************************************************
Macro Definition 宏定义
*******************************************************************************/
#define ADC_Assert(expr) UlogAssert(expr,while(1))
#define ADC_ERR(fmt,...) ULOG_E(fmt,##__VA_ARGS__)
#define ADC_WRNG(fmt,...) ULOG_W(fmt,##__VA_ARGS__)
#define ADC_INFO(fmt,...) ULOG_I(fmt,##__VA_ARGS__)
#define ADC_DBUG(fmt,...) ULOG_D(fmt,##__VA_ARGS__)
/*******************************************************************************
Type declaration 类型声明
********************************************************************************/
/// ADC错误代码
typedef enum
{
ADC_OK = 0,
ADC_INIT_ERR = -1,
ADC_INIT_CH_ERR = -2,
ADC_INIT_AWDOG_ERR = -3,
ADC_INIT_DMA_ERR = -4,
ADC_INIT_TIMER_ERR = -5,
}ADC_Err;
/// ADC通道代码(最大通道数量虽然有20个通道,但是常规转换顺序只有1~16)
typedef enum
{
ADC_CH0,
ADC_CH1,
ADC_CH2,
ADC_CH3,
ADC_CH4,
ADC_CH5,
ADC_CH6,
ADC_CH7,
ADC_CH8,
ADC_CH9,
ADC_CH10,
ADC_CH11,
ADC_CH12,
ADC_CH13,
ADC_CH14,
ADC_CH15,
ADC_CH16,
ADC_CH17,
ADC_CH18,
ADC_CH19,
ADC_CH_MAX_NUM,
}ADC_Ch;
typedef struct adc_dev
{
ADC_TypeDef* adc;
uint32_t ch[ADC_CH_MAX_NUM]; //ADC通道配置
uint8_t ch_num; //ADC通道数量
ADC_HandleTypeDef hadc;
DMA_HandleTypeDef hdma_adc;
struct //环形buf
{
uint16_t* data;
size_t len;
}buf;
}ADC_dev;
/*******************************************************************************
Function declaration 函数声明
*******************************************************************************/
int ADC_Init(ADC_dev* dev);
int ADC_InitTimer(ADC_dev* dev,uint32_t Freq);
void ADC_Stop(void);
void ADC_Start(void);
void ADC_GetChVal(ADC_dev* dev, uint32_t* buf, uint32_t len, uint32_t ch);
#endif
执行过程
|
|