最近在做一个项目,用到的主控芯片是沁恒微的WCH32v003,其中一个功能是多通道采集ADC+DMA运输,在编写代码的时候想找官方的库函数文件,但是找了很久都没有找到,官网只有一个数据手册和应用手册,而应用手册一般是分为库函数应用手册和寄存器应用手册,但是官网上的应用手册是只有寄存器的,而官方的库又用了大量的封装,所以看起来特别的痛苦,于是我结合网上的资料和自己的理解,总结处理一个关于ADC采集的库函数介绍,希望可以帮助到大家。
1.1、void ADC_DeInit(ADC_TypeDef* ADCx)
功 能:将ADCx外围寄存器初始化为其默认重置值。
输 入:ADCx:其中x可以是1以选择ADC外围设备。
1.2、void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct)
功 能:根据ADC_InitStruct中指定的参数初始化ADCx外围设备。
输 入:ADCx:其中x可以是1以选择ADC外围设备;ADC_InitStruct:指向包含指定ADC外围设备的配置信息的ADC_InitTypeDef结构的指针。
1.3、void ADC_StructInit(ADC_InitTypeDef* ADC_InitStruct)
功 能:用默认值填充每个ADC_InitStruct成员。
输 入:ADC_InitStruct:指向包含指定ADC外围设备的配置信息的ADC_InitTypeDef结构的指针。
1.4、void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState)
功 能:启用或禁用指定的ADC外围设备。
输 入:ADCx:其中x可以是1以选择ADC外围设备;NewState:启用或禁用。
1.5、void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState)
功 能:启用或禁用指定的ADC DMA请求。
输 入:ADCx:其中x可以是1以选择ADC外围设备;NewState:启用或禁用。
1.6、void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState)
功 能:启用或禁用指定的ADC中断。
输 入:ADCx:其中x可以是1以选择ADC外围设备;ADC_IT:指定要启用或禁用的ADC中断源。NewState:启用或禁用。
1.7、void ADC_ResetCalibration(ADC_TypeDef* ADCx)
功 能:重置所选ADC校准寄存器。
输 入:ADCx:其中x可以是1以选择ADC外围设备。
1.8、FlagStatus ADC_GetResetCalibrationStatus(ADC_TypeDef* ADCx)
功 能:获取所选ADC重置校准寄存器状态。
输 入:ADCx:其中x可以是1以选择ADC外围设备。
1.9、void ADC_StartCalibration(ADC_TypeDef* ADCx)
功 能:启动所选ADC校准过程。
输 入:ADCx:其中x可以是1以选择ADC外围设备。
1.10、FlagStatus ADC_GetCalibrationStatus(ADC_TypeDef* ADCx)
功 能:获取所选ADC校准状态。
输 入:ADCx:其中x可以是1以选择ADC外围设备。
1.11、void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState)
功 能:启用或禁用所选ADC软件启动转换。
输 入:ADCx:其中x可以是1以选择ADC外围设备;NewState:启用或禁用。
1.12、FlagStatus ADC_GetSoftwareStartConvStatus(ADC_TypeDef* ADCx)
功 能:获取所选ADC软件开始转换状态。
输 入:ADCx:其中x可以是1以选择ADC外围设备。
1.13、void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number)
功 能:为所选ADC常规组通道配置不连续模式。
输 入:ADCx:其中x可以是1以选择ADC外围设备;Number:指定不连续模式常规通道计数值。
1.14、void ADC_DiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState)
功 能:为指定的ADC启用或禁用常规组通道上的不连续模式。
输 入:ADCx:其中x可以是1以选择ADC外围设备;NewState:启用或禁用。
1.15、void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime)
功 能:为所选ADC常规通道配置其在序列器中的相应列组及其采样时间。
输 入:ADCx:其中x可以是1以选择ADC外围设备;ADC_Channel:要配置的ADC信道;Rank:常规组序列器中的等级;ADC_SampleTime:要为所选通道设置的采样时间值。
1.16、void ADC_ExternalTrigConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState)
功 能:通过外部触发器启用或禁用ADCx转换。
输 入:ADCx:其中x可以是1以选择ADC外围设备;NewState:启用或禁用。
1.17、uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx)
功 能:返回常规通道的最后一个ADCx转换结果数据。
输 入:ADCx:其中x可以是1以选择ADC外围设备。
1.18、uint32_t ADC_GetDualModeConversionValue(void)
功 能:以双模式返回最后一个ADC1和ADC2转换结果数据。
输 入:无。
1.19、void ADC_AutoInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState)
功 能:启用或禁用所选ADC在常规转换后自动注入组转换。
输 入:ADCx:其中x可以是1以选择ADC外围设备;NewState:启用或禁用。
1.20、void ADC_InjectedDiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState)
功 能:为指定的ADC启用或禁用注入组通道的不连续模式。
输 入:ADCx:其中x可以是1以选择ADC外围设备;NewState:启用或禁用。
1.21、void ADC_ExternalTrigInjectedConvConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConv)
功 能:为注入通道转换配置ADCx外部触发器。
输 入:ADCx:其中x可以是1以选择ADC外围设备;ADC_ExternalTrigInjecConv:指定开始注入转换的ADC触发器。
1.22、void ADC_ExternalTrigInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState)
功 能:通过外部触发器启用或禁用ADCx注入通道转换。
输 入:ADCx:其中x可以是1以选择ADC外围设备;NewState:启用或禁用。
1.23、void ADC_SoftwareStartInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState)
功 能:启用或禁用注入通道转换的所选ADC启动。
输 入:ADCx:其中x可以是1以选择ADC外围设备;NewState:启用或禁用。
1.24、FlagStatus ADC_GetSoftwareStartInjectedConvCmdStatus(ADC_TypeDef* ADCx)
功 能:获取所选ADC软件开始注入转换状态。
输 入:ADCx:其中x可以是1以选择ADC外围设备。
1.25、void ADC_InjectedChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime)
功 能:为所选ADC注入通道配置其在序列器中的相应秩及其采样时间。
输 入:ADCx:其中x可以是1以选择ADC外围设备;ADC_Channel:要配置的ADC信道;Rank:注入组序列器中的秩;ADC_SampleTime:要为所选通道设置的采样时间值。
1.26、void ADC_InjectedSequencerLengthConfig(ADC_TypeDef* ADCx, uint8_t Length)
功 能:配置注入通道的序列器长度。
输 入:ADCx:其中x可以是1以选择ADC外围设备;Length:序列器的长度。
1.27、void ADC_SetInjectedOffset(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel, uint16_t Offset)
功 能:设置注入通道转换值偏移。
输 入:ADCx:其中x可以是1以选择ADC外围设备;Offset:所选ADC注入通道的偏移值。
1.28、uint16_t ADC_GetInjectedConversionValue(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel)
功 能:ADC返回注入通道的结果。
输 入:ADCx:其中x可以是1以选择ADC外围设备;ADC_InjectedChannel:转换后的ADC注入通道。
1.29、void ADC_AnalogWatchdogCmd(ADC_TypeDef* ADCx, uint32_t ADC_AnalogWatchdog)
功 能:启用或禁用单个/所有常规或注入通道上的模拟看门狗。
输 入:ADCx:其中x可以是1以选择ADC外围设备;ADC_AnalogWatchdog:ADC模拟看门狗配置。
1.30、void ADC_AnalogWatchdogThresholdsConfig(ADC_TypeDef* ADCx, uint16_t HighThreshold,uint16_t LowThreshold)
功 能:配置模拟看门狗的高阈值和低阈值。
输 入:ADCx:其中x可以是1以选择ADC外围设备;HighThreshold:ADC模拟看门狗高阈值;LowThreshold:ADC模拟看门狗低阈值。
1.31、void ADC_AnalogWatchdogSingleChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel)
功 能:配置模拟看门狗保护的单通道。
输 入:ADCx:其中x可以是1以选择ADC外围设备;ADC_Channel:为模拟看门狗配置的ADC信道。
1.32、void ADC_TempSensorVrefintCmd(FunctionalState NewState)
功 能:启用或禁用温度传感器和Vrefint通道。
输 入:NewState:启用或禁用。
1.33、FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG)
功 能:检查是否设置了指定的ADC标志。
输 入:ADCx:其中x可以是1以选择ADC外围设备;ADC_FLAG:指定要检查的标志。
1.34、void ADC_ClearFlag(ADC_TypeDef* ADCx, uint8_t ADC_FLAG)
功 能:清除ADCx的挂起标志。
输 入:ADCx:其中x可以是1以选择ADC外围设备;ADC_FLAG:指定要清除的标志。
1.35、ITStatus ADC_GetITStatus(ADC_TypeDef* ADCx, uint16_t ADC_IT)
功 能:检查指定的ADC中断是否已发生。
输 入:ADCx:其中x可以是1以选择ADC外围设备;ADC_IT:指定要检查的ADC中断源。
1.36、void ADC_ClearITPendingBit(ADC_TypeDef* ADCx, uint16_t ADC_IT)
功 能:清除ADCx的中断挂起位。
输 入:ADCx:其中x可以是1以选择ADC外围设备;ADC_IT:指定要清除的ADC中断挂起位。
1.37、s32 TempSensor_Volt_To_Temper(s32 Value)
功 能:内部温度传感器电压与温度之间的关系。
输 入:Value:电压值。
这里是参考wch32v103的,基本上都是一样的,原文地址:十、CH32V103应用教程——ADC - RISC-V技术及应用论坛,开源指令集架构(ISA)论坛 - 21ic电子技术开**坛
下面的代码部分,是可以直接使用的,具体就不做过多介绍了,对照这上面的库函数介绍都很容易理解。我的代码是3通道采集,大家可以根据自己的实际需求更改。下面是不同封装的引脚定义。
main.c
#include "debug.h"
/* Global Variable */
u16 TxBuf[10];
/*********************************************************************
* @fn ADC_Function_Init
*
* @brief Initializes ADC collection.
*
* @return none
*/
void ADC_Function_Init(void)
{
ADC_InitTypeDef ADC_InitStructure = {0};
GPIO_InitTypeDef GPIO_InitStructure = {0};
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div8);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOD, &GPIO_InitStructure);
ADC_DeInit(ADC1);
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 3;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_Calibration_Vol(ADC1, ADC_CALVOL_50PERCENT);
ADC_DMACmd(ADC1, ENABLE);
ADC_Cmd(ADC1, ENABLE);
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
}
/*********************************************************************
* @fn Get_ADC_Val
*
* @brief Returns ADCx conversion result data.
*
* @param ch - ADC channel.
* ADC_Channel_0 - ADC Channel0 selected.
* ADC_Channel_1 - ADC Channel1 selected.
* ADC_Channel_2 - ADC Channel2 selected.
* ADC_Channel_3 - ADC Channel3 selected.
* ADC_Channel_4 - ADC Channel4 selected.
* ADC_Channel_5 - ADC Channel5 selected.
* ADC_Channel_6 - ADC Channel6 selected.
* ADC_Channel_7 - ADC Channel7 selected.
* ADC_Channel_8 - ADC Channel8 selected.
* ADC_Channel_9 - ADC Channel9 selected.
*
* @return none
*/
u16 Get_ADC_Val(u8 ch)
{
u16 val;
ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_241Cycles);
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
val = ADC_GetConversionValue(ADC1);
return val;
}
/*********************************************************************
* @fn DMA_Tx_Init
*
* @brief Initializes the DMAy Channelx configuration.
*
* @param DMA_CHx - x can be 1 to 7.
* ppadr - Peripheral base address.
* memadr - Memory base address.
* bufsize - DMA channel buffer size.
*
* @return none
*/
void DMA_Tx_Init(DMA_Channel_TypeDef *DMA_CHx, u32 ppadr, u32 memadr, u16 bufsize)
{
DMA_InitTypeDef DMA_InitStructure = {0};
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
DMA_DeInit(DMA_CHx);
DMA_InitStructure.DMA_PeripheralBaseAddr = ppadr;
DMA_InitStructure.DMA_MemoryBaseAddr = memadr;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = bufsize;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA_CHx, &DMA_InitStructure);
}
/*********************************************************************
* @fn main
*
* @brief Main program.
*
* @return none
*/
int main(void)
{
u16 i;
SystemCoreClockUpdate();
Delay_Init();
#if (SDI_PRINT == SDI_PR_OPEN)
SDI_Printf_Enable();
#else
USART_Printf_Init(115200);
#endif
printf("SystemClk:%d\r\n", SystemCoreClock);
printf( "ChipID:%08x\r\n", DBGMCU_GetCHIPID() );
ADC_Function_Init();
DMA_Tx_Init(DMA1_Channel1, (u32)&ADC1->RDATAR, (u32)TxBuf,3);
while(1)
{
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 1, ADC_SampleTime_241Cycles);
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 2, ADC_SampleTime_241Cycles);
ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 3, ADC_SampleTime_241Cycles);
DMA_Cmd(DMA1_Channel1, ENABLE);
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
Delay_Ms(5);
ADC_SoftwareStartConvCmd(ADC1, DISABLE);
DMA_Cmd(DMA1_Channel1, DISABLE);
for(i = 0; i < 3; i++)
{
printf("%04d\r\n", TxBuf);
Delay_Ms(10);
}
Delay_Ms(50);
}
}
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/abc565846881/article/details/135936553
|
|