- #include "debug.h"
- static uint8_t p_us = 0;
- static uint16_t p_ms = 0;
- void Delay_Init(void)
- {
- p_us = SystemCoreClock / 8000000;
- p_ms = (uint16_t)p_us * 1000;
- }
- void Delay_Us(uint32_t n)
- {
- uint32_t i;
- SysTick->SR &= ~(1 << 0);
- i = (uint32_t)n * p_us;
- SysTick->CMP = i;
- SysTick->CTLR |= (1 << 4) | (1 << 5) | (1 << 0);
- while((SysTick->SR & (1 << 0)) != (1 << 0))
- ;
- SysTick->CTLR &= ~(1 << 0);
- }
- /*********************************************************************
- * @fn Delay_Ms
- *
- * [url=/u/brief]@brief[/url] Millisecond Delay Time.
- *
- * @param n - Millisecond number.
- *
- * [url=/u/return]@return[/url] None
- */
- void Delay_Ms(uint32_t n)
- {
- uint32_t i;
- SysTick->SR &= ~(1 << 0);
- i = (uint32_t)n * p_ms;
- SysTick->CMP = i;
- SysTick->CTLR |= (1 << 4) | (1 << 5) | (1 << 0);
- while((SysTick->SR & (1 << 0)) != (1 << 0))
- ;
- SysTick->CTLR &= ~(1 << 0);
- }
- /*********************************************************************
- * @fn USART_Printf_Init
- *
- * @brief Initializes the USARTx peripheral.
- *
- * @param baudrate - USART communication baud rate.
- *
- * @return None
- */
- void USART_Printf_Init(uint32_t baudrate)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- USART_InitTypeDef USART_InitStructure;
- #if(DEBUG == DEBUG_UART1)
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- #elif(DEBUG == DEBUG_UART2)
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- #elif(DEBUG == DEBUG_UART3)
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
- #endif
- USART_InitStructure.USART_BaudRate = baudrate;
- USART_InitStructure.USART_WordLength = USART_WordLength_8b;
- USART_InitStructure.USART_StopBits = USART_StopBits_1;
- USART_InitStructure.USART_Parity = USART_Parity_No;
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
- USART_InitStructure.USART_Mode = USART_Mode_Tx;
- #if(DEBUG == DEBUG_UART1)
- USART_Init(USART1, &USART_InitStructure);
- USART_Cmd(USART1, ENABLE);
- #elif(DEBUG == DEBUG_UART2)
- USART_Init(USART2, &USART_InitStructure);
- USART_Cmd(USART2, ENABLE);
- #elif(DEBUG == DEBUG_UART3)
- USART_Init(USART3, &USART_InitStructure);
- USART_Cmd(USART3, ENABLE);
- #endif
- }
- /*********************************************************************
- * @fn _write
- *
- * @brief Support Printf Function
- *
- * @param *buf - UART send Data.
- * size - Data length
- *
- * @return size: Data length
- */
- __attribute__((used)) int _write(int fd, char *buf, int size)
- {
- int i;
- for(i = 0; i < size; i++)
- {
- #if(DEBUG == DEBUG_UART1)
- while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
- USART_SendData(USART1, *buf++);
- #elif(DEBUG == DEBUG_UART2)
- while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
- USART_SendData(USART2, *buf++);
- #elif(DEBUG == DEBUG_UART3)
- while(USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET);
- USART_SendData(USART3, *buf++);
- #endif
- }
- return size;
- }
- /*********************************************************************
- * @fn _sbrk
- *
- * @brief Change the spatial position of data segment.
- *
- * @return size: Data length
- */
- void *_sbrk(ptrdiff_t incr)
- {
- extern char _end[];
- extern char _heap_end[];
- static char *curbrk = _end;
- if ((curbrk + incr < _end) || (curbrk + incr > _heap_end))
- return NULL - 1;
- curbrk += incr;
- return curbrk - incr;
- }
ADC_Function_Init(void)的核心作用是:初始化 CH32V307 的 ADC1 外设,配置其工作模式、采样通道(GPIOA_Pin2)、转换方式等参数,并完成 ADC 校准,最终使能 ADC 以持续采集模拟信号。
CH32V307 时钟特性:ADC1 挂载在 APB2 总线上,需通过RCC_APB2PeriphClockCmd开启时钟;ADC 时钟(ADCCLK)由 APB2 时钟(PCLK2)分频得到,此处配置为PCLK2/8。若系统时钟为 144MHz,APB2 时钟为 144MHz,则 ADCCLK = 144/8 = 18MHz(CH32V307 的 ADC 最高支持 36MHz 时钟)。
连续转换模式:ENABLE表示 ADC 在一次转换完成后会自动开始下一次转换,适合需要持续采集信号的场景(如传感器实时监测);数据对齐:CH32V307 的 ADC 为 12 位精度(取值范围 0~4095),右对齐时结果直接存储在ADC_DR寄存器的低 12 位,便于读取;无外部触发:由软件触发开始第一次转换(后续因连续模式自动触发)。
- /*
- *[url=/u/NOTE]@NOTE[/url]
- ADC使用DMA采样例程:
- ADC通道2(PA2),规则组通道通过DMA获取 ADC连续1024次转换数据。
-
- */
- #include "debug.h"
- /* Global Variable */
- u16 TxBuf[1024];
- s16 Calibrattion_Val = 0;
- /*********************************************************************
- * @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_GPIOA, ENABLE );
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE );
- RCC_ADCCLKConfig(RCC_PCLK2_Div8);
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- ADC_DeInit(ADC1);
- ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
- ADC_InitStructure.ADC_ScanConvMode = DISABLE;
- ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
- ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
- ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
- ADC_InitStructure.ADC_NbrOfChannel = 1;
- ADC_Init(ADC1, &ADC_InitStructure);
- ADC_DMACmd(ADC1, ENABLE);
- ADC_Cmd(ADC1, ENABLE);
- ADC_BufferCmd(ADC1, DISABLE); //disable buffer
- ADC_ResetCalibration(ADC1);
- while(ADC_GetResetCalibrationStatus(ADC1));
- ADC_StartCalibration(ADC1);
- while(ADC_GetCalibrationStatus(ADC1));
- Calibrattion_Val = Get_CalibrationValue(ADC1);
-
- ADC_BufferCmd(ADC1, ENABLE); //enable buffer
- }
- /*********************************************************************
- * @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.
- * ADC_Channel_10 - ADC Channel10 selected.
- * ADC_Channel_11 - ADC Channel11 selected.
- * ADC_Channel_12 - ADC Channel12 selected.
- * ADC_Channel_13 - ADC Channel13 selected.
- * ADC_Channel_14 - ADC Channel14 selected.
- * ADC_Channel_15 - ADC Channel15 selected.
- * ADC_Channel_16 - ADC Channel16 selected.
- * ADC_Channel_17 - ADC Channel17 selected.
- *
- * @return none
- */
- u16 Get_ADC_Val(u8 ch)
- {
- u16 val;
- ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 );
- 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_Normal;
- DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
- DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
- DMA_Init( DMA_CHx, &DMA_InitStructure );
- }
- /*********************************************************************
- * @fn Get_ConversionVal
- *
- * @brief Get Conversion Value.
- *
- * @param val - Sampling value
- *
- * @return val+Calibrattion_Val - Conversion Value.
- */
- u16 Get_ConversionVal(s16 val)
- {
- if((val+Calibrattion_Val)<0) return 0;
- if((Calibrattion_Val+val)>4095) return 4095;
- return (val+Calibrattion_Val);
- }
CH32V307 ADC MDA的使用场景:该配置适用于单通道连续采集模拟信号(如电压、温度、光照等传感器),通过 DMA 传输结果可减少 CPU 干预;
若需多通道采集,需修改ADC_ScanConvMode = ENABLE并增加ADC_NbrOfChannel数量,同时配置通道转换顺序。
采集NTC10K
- float Calculate_Temperature(uint16_t adc_value)
- {
- float voltage, resistance, temperature;
-
- // 将ADC值转换为电压 (假设Vref=3.3V)
- voltage = (adc_value * 3.3f) / 4095.0f;
-
- // 计算NTC电阻值
- resistance = (voltage * REFERENCE_RESISTANCE) / (3.3f - voltage);
-
- // 使用B参数方程计算温度
- temperature = resistance / RESISTANCE_NOMINAL;
- temperature = log(temperature);
- temperature /= B_VALUE;
- temperature += 1.0f / (TEMPERATURE_NOMINAL + 273.15f);
- temperature = 1.0f / temperature;
- temperature -= 273.15f; // 转换为摄氏度
-
- return temperature;
- }
main
- int main(void)
- {
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
- USART_Printf_Init(115200);
- printf("CH32V307 NTC Temperature Sensor Demo\r\n");
-
- ADC_Function_Init();
- printf("ADC Initialized, reading NTC on PA2 (ADC1_IN2)\r\n");
-
- while(1)
- {
- // 多次采样取平均值,减少噪声
- uint32_t sum = 0;
- for(int i = 0; i < 10; i++)
- {
- sum += Get_ADC_Value();
- Delay_Ms(10);
- }
- ADC_Value = sum / 10;
-
- // 计算温度
- temperature = Calculate_Temperature(ADC_Value);
-
- // 打印结果
- printf("ADC Value: %d, Voltage: %.2fV, Temperature: %.2f°C\r\n",
- ADC_Value,
- (ADC_Value * 3.3f) / 4095.0f,
- temperature);
-
- Delay_Ms(1000); // 每秒更新一次
- }
- }
运行结果
- CH32V307 NTC Temperature Sensor Demo
- ADC Initialized, reading NTC on PA2 (ADC1_IN2)
- ADC Value: 2048, Voltage: 1.65V, Temperature: 25.01°C
- ADC Value: 2045, Voltage: 1.65V, Temperature: 25.12°C
- ADC Value: 2050, Voltage: 1.65V, Temperature: 24.98°C
- ADC Value: 2047, Voltage: 1.65V, Temperature: 25.05°C
- ADC Value: 2043, Voltage: 1.64V, Temperature: 25.23°C
- ADC Value: 2052, Voltage: 1.66V, Temperature: 24.87°C
- ADC Value: 2049, Voltage: 1.65V, Temperature: 24.99°C
- ADC Value: 2046, Voltage: 1.65V, Temperature: 25.09°C
- ...