江科大ADC模数转换hal库实现
ADC,anology digital convert,把对应的引脚得到的模拟量转换成数字量给单片机。
ADC相关hal库函数
ADC初始化结构体
typedef struct
{uint32_t DataAlign; /*数据对齐方式*/uint32_t ScanConvMode; /*数据扫描连续模式 */FunctionalState ContinuousConvMode; /*连续扫描模式*/uint32_t NbrOfConversion; /*数据扫描通道*/FunctionalState DiscontinuousConvMode; /*数据扫描间隔模式 */uint32_t NbrOfDiscConversion; /*数据间隔扫描分组*/uint32_t ExternalTrigConv; /*外部触发转换模式*/
}ADC_InitTypeDef;
ADC通道初始化
typedef struct
{uint32_t Channel; /*通道选择*/uint32_t Rank; /*通道排序*/uint32_t SamplingTime; /*通道采样时间 */
}ADC_ChannelConfTypeDef;
ADC句柄
typedef struct __ADC_HandleTypeDef
{ADC_TypeDef *Instance; /*ADC地址*/ADC_InitTypeDef Init; /*ADC初始化结构体*/DMA_HandleTypeDef *DMA_Handle; /*DMA初始化结构体*/HAL_LockTypeDef Lock; /*ADC句柄配置锁 */__IO uint32_t State; /*ADC状态 */__IO uint32_t ErrorCode; /*ADC错误标志位*/#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)//ADC回调函数void (* ConvCpltCallback)(struct __ADC_HandleTypeDef *hadc); /*!< ADC conversion complete callback */void (* ConvHalfCpltCallback)(struct __ADC_HandleTypeDef *hadc); /*!< ADC conversion DMA half-transfer callback */void (* LevelOutOfWindowCallback)(struct __ADC_HandleTypeDef *hadc); /*!< ADC analog watchdog 1 callback */void (* ErrorCallback)(struct __ADC_HandleTypeDef *hadc); /*!< ADC error callback */void (* InjectedConvCpltCallback)(struct __ADC_HandleTypeDef *hadc); /*!< ADC group injected conversion complete callback */ /*!< ADC end of sampling callback */void (* MspInitCallback)(struct __ADC_HandleTypeDef *hadc); /*!< ADC Msp Init callback */void (* MspDeInitCallback)(struct __ADC_HandleTypeDef *hadc); /*!< ADC Msp DeInit callback */
#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
}ADC_HandleTypeDef;
从中我们可以看出ADC的中断数量是比较少的,有一个传输完成中断,一个传输过半中断,一个模拟看门狗中断,一个错误中断,一个注入组的额外注入组完成中断,接着就是初始化的回调函数。
ADC初始化函数
HAL_StatusTypeDef HAL_ADC_Init(ADC_HandleTypeDef* hadc);
HAL_StatusTypeDef HAL_ADC_DeInit(ADC_HandleTypeDef *hadc);
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc);
void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc);
hal库外设的初始化基本都是靠句柄来完成的。
HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef* hadc);
HAL_StatusTypeDef HAL_ADC_Stop(ADC_HandleTypeDef* hadc);
HAL_StatusTypeDef HAL_ADC_PollForConversion(ADC_HandleTypeDef* hadc, uint32_t Timeout);
HAL_StatusTypeDef HAL_ADC_PollForEvent(ADC_HandleTypeDef* hadc, uint32_t EventType, uint32_t Timeout);
ADC开启,停止,轮训方式询问转换,轮训方式等待事件的发送,
HAL_StatusTypeDef HAL_ADC_Start_IT(ADC_HandleTypeDef* hadc);
HAL_StatusTypeDef HAL_ADC_Stop_IT(ADC_HandleTypeDef* hadc);
HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length);
HAL_StatusTypeDef HAL_ADC_Stop_DMA(ADC_HandleTypeDef* hadc);
uint32_t HAL_ADC_GetValue(ADC_HandleTypeDef* hadc);
ADC开关中断,使用或停止DMA的数据转运,获取ADC转换结果。如果我们用到了DMA来转运ADC数据,就可以在初始化的句柄那边顺带初始化DMA,调用ADC开启DMA函数就能让DMA自动转运我们ADC转换的结果到我们期望存放的地方去。
void ADC_StabilizationTime(uint32_t DelayUs);
配置 ADC(模拟数字转换器)稳定时间的函数
单通道ADC转换
按照江科大的配置来设置,ADC选择ADC1,的通道0,硬件图上对应的引脚就是
PA0
ADC最大的时钟频率是14Mhz,我们对72Mhz进行6分频
独立模式, 数据右对齐,非连续模式,非扫描模式,非间隔模式,使用规则通道,通道数为1,软件出发,序号为1,通道0,采样时间为默认的1.5个时间周期。
后面的注入组和模拟看门狗不需要我们配置,默认即可。
uint16_t AD_GetValue(void)
{HAL_ADC_Start(&hadc1);//启动一次软件触发ADC//while (__HAL_ADC_GET_FLAG(&hadc1, ADC_FLAG_EOC) == RESET); //等待EOC标志位,即等待AD转换结束while(HAL_ADC_PollForConversion(&hadc1,1000) != HAL_OK);//等待AD转换结束return HAL_ADC_GetValue(&hadc1); //读数据寄存器,得到AD转换的结果
}
初始化完成后,我们只需要把江科大的ADC读取代码修改成我们自己的就行了。
等待标志位EOC的到来,我们可以用hal库给的宏定义直接询问也可以用hal库封装的轮训函数进行等待,轮训函数多了个超时机制,更加的安全,而宏定义更适用于对时间小,对精度要求更高的地方。两种方法在这里都是可以正常使用的。
多通道ADC转换
多通道转换就得对多通道进行通道排序了,其他的就没什么区别了。
独立模式,外部软件触发,非连续转换,非扫描模式,通道数为1,采样时间1.5个时间周期。
江科大是通过修改对应的ADC通道的排序,来获取多个不同的ADC通道值的,在访问的时候修改我们要访问的ADC通道的排序为1。
我们先默认通道0的排序为1,函数里面进行改,这样配置下来,ADC多通道也就是多选择了几个ADC1的通道,别的设置没有任何变化。
uint16_t AD_GetValue(uint8_t ADC_Channel)
{ ADC_ChannelConfTypeDef sConfig = {0};sConfig.Channel = ADC_Channel;sConfig.Rank = ADC_REGULAR_RANK_1;sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)//在每次转换前,根据函数形参灵活更改规则组的通道1{Error_Handler();}HAL_ADC_Start(&hadc1);//软件触发AD转换一次while(HAL_ADC_PollForConversion(&hadc1,1000));//等待EOC标志位,即等待AD转换结束return HAL_ADC_GetValue(&hadc1);//读数据寄存器,得到AD转换的结果
}
直接仿照江科大的代码,把标准库的代码更换为hal库的相关代码即可完成。