前言
stm32f103有多路12位ADC,外部参考电压一般使用3.3V, 理论上STM32F103是在CPU频率为56MHz时,ADC的最大采样转换频率达到1MHz。但是当CPU频率为72MHz时,ADC的最大采样转换频率变为854.7kHz,即1.17us,比1MHz慢。而AT32F403A主频可达240MHZ, 3组2M采样速率12位A/D转换器(21通道)
最小采样周期为1.5个周期+12.5周期=14周期。
最大采样频率为:12MHZ/14周期=851.142KHZ≈851KHZ
也就是1s可以采样851K个数据,这个采样率已经可以满足很多应用需要了。
其中PA0~PA3 分别对应ADC_CHANNEL_0到ADC_CHANNEL_3
其中PC0~PC3 分别对应ADC_CHANNEL_10到ADC_CHANNEL_13
1. 头文件 adc.h
代码使用的是 AT32F403A_407_Firmware_Library_V2.0.8版本库进行编写,也可以通过JLINK烧录到STM32F103上使用:
#ifndef __ADC_H
#define __ADC_H
#include "sys.h"
#define FIRL_N 8
#define AD_NUM 8
/**
* @brief tmr channel select type
*/
typedef enum
{
AD_INPUT = 0x00, /*!< ad channel select channel 1 */
DAT_INPUT = 0x01, /*!< ad channel select channel 1 complementary */
} Sysctrl_Input_select_type;
extern __IO uint32_t dma1_trans_complete_flag;
extern __IO uint16_t vmor_flag_index;
extern __IO uint16_t ADValue[FIRL_N][AD_NUM];
void Get_ADValue(u16* value);
void App_MutiAdcCfg(void);
void PilotAnalogToBuf(uint8_t *rptr, uint8_t *wptr,uint16_t *buf,uint8_t cnt);
extern __IO double fatualvot[AD_NUM];
#endif
2. 源文件adc.c
程序配置了PA0到PA3, PC0到PC3 八路ADC进行采集,采用DMA方式进行存储,ADValue[FIRL_N][AD_NUM] 用来存放ADC转换结果,也是DMA的目标地址,每完成一次转换,DMA将数据依次存放到数组
#include "adc.h"
#include "at32f403a_407_board.h"
__IO uint16_t ADValue[FIRL_N][AD_NUM];
__IO uint16_t ADValFilter[AD_NUM];
__IO uint32_t dma1_trans_complete_flag = 0;
static void adc_gpio_config(void);
static void dma_config(void);
static void adc_config(void);
/**
* @brief gpio configuration.
* @param none
* @retval none
*/
static void adc_gpio_config(void)
{
gpio_init_type gpio_initstructure;
crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE);
gpio_default_para_init(&gpio_initstructure);
gpio_initstructure.gpio_mode = GPIO_MODE_ANALOG;
gpio_initstructure.gpio_pins = GPIO_PINS_0 | GPIO_PINS_1 | GPIO_PINS_2 | GPIO_PINS_3;
gpio_init(GPIOA, &gpio_initstructure);
gpio_initstructure.gpio_mode = GPIO_MODE_ANALOG;
gpio_initstructure.gpio_pins = GPIO_PINS_0 | GPIO_PINS_1 | GPIO_PINS_2 | GPIO_PINS_3;
gpio_init(GPIOC, &gpio_initstructure);
}
/**
* @brief dma configuration.
* @param none
* @retval none
*/
static void dma_config(void)
{
dma_init_type dma_init_struct;
crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);
// nvic_irq_enable(DMA1_Channel1_IRQn, 0, 0);
dma_reset(DMA1_CHANNEL1);
dma_default_para_init(&dma_init_struct);
dma_init_struct.buffer_size = FIRL_N*AD_NUM;
dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;
dma_init_struct.memory_base_addr = (uint32_t)ADValue;
dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_HALFWORD;
dma_init_struct.memory_inc_enable = TRUE;
dma_init_struct.peripheral_base_addr = (uint32_t)&(ADC1->odt);
dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_HALFWORD;
dma_init_struct.peripheral_inc_enable = FALSE;
dma_init_struct.priority = DMA_PRIORITY_HIGH;
dma_init_struct.loop_mode_enable = TRUE;
dma_init(DMA1_CHANNEL1, &dma_init_struct);
// dma_interrupt_enable(DMA1_CHANNEL1, DMA_FDT_INT, TRUE);
dma_channel_enable(DMA1_CHANNEL1, TRUE);
}
/**
* @brief adc configuration.
* @param none
* @retval none
*/
static void adc_config(void)
{
adc_base_config_type adc_base_struct;
crm_periph_clock_enable(CRM_ADC1_PERIPH_CLOCK, TRUE);
crm_adc_clock_div_set(CRM_ADC_DIV_6);
/* select combine mode */
adc_combine_mode_select(ADC_INDEPENDENT_MODE);
adc_base_default_para_init(&adc_base_struct);
adc_base_struct.sequence_mode = TRUE;
adc_base_struct.repeat_mode = TRUE;
adc_base_struct.data_align = ADC_RIGHT_ALIGNMENT;
adc_base_struct.ordinary_channel_length = AD_NUM;
adc_base_config(ADC1, &adc_base_struct);
adc_ordinary_channel_set(ADC1, ADC_CHANNEL_0, 1, ADC_SAMPLETIME_239_5);
adc_ordinary_channel_set(ADC1, ADC_CHANNEL_1, 2, ADC_SAMPLETIME_239_5);
adc_ordinary_channel_set(ADC1, ADC_CHANNEL_2, 3, ADC_SAMPLETIME_239_5);
adc_ordinary_channel_set(ADC1, ADC_CHANNEL_3, 4, ADC_SAMPLETIME_239_5);
adc_ordinary_channel_set(ADC1, ADC_CHANNEL_10, 5, ADC_SAMPLETIME_239_5);
adc_ordinary_channel_set(ADC1, ADC_CHANNEL_11, 6, ADC_SAMPLETIME_239_5);
adc_ordinary_channel_set(ADC1, ADC_CHANNEL_12, 7, ADC_SAMPLETIME_239_5);
adc_ordinary_channel_set(ADC1, ADC_CHANNEL_13, 8, ADC_SAMPLETIME_239_5);
adc_ordinary_conversion_trigger_set(ADC1, ADC12_ORDINARY_TRIG_SOFTWARE, TRUE);
adc_dma_mode_enable(ADC1, TRUE);
adc_enable(ADC1, TRUE);
adc_calibration_init(ADC1);
while(adc_calibration_init_status_get(ADC1));
adc_calibration_start(ADC1);
while(adc_calibration_status_get(ADC1));
}
void App_MutiAdcCfg(void)
{
adc_gpio_config();
dma_config();
adc_config();
}
3. 软件滤波程序
void Get_ADValue(u16* value)
{
u8 i,chnl;
for (i=0;i<AD_NUM;i++)
{
ADValFilter=0;
}
for(chnl=0; chnl<AD_NUM; chnl++)
{
for(i=0;i<FIRL_N;i++)
{
ADValFilter[chnl]+=ADValue[chnl];
}
ADValFilter[chnl]>>=3;
if(ADValFilter[chnl]<9)ADValFilter[chnl] = 9;
ADValFilter[chnl] -= 9;
*value++ = ADValFilter[chnl];
}
}
4. 主函数main.c
/**
**************************************************************************
* @file main.c
* @version v2.0.8
* @date 2022-04-02
* @brief main program
**************************************************************************
* Copyright notice & Disclaimer
*
* The software Board Support Package (BSP) that is made available to
* download from Artery official website is the copyrighted work of Artery.
* Artery authorizes customers to use, copy, and distribute the BSP
* software and its related documentation for the purpose of design and
* development in conjunction with Artery microcontrollers. Use of the
* software is governed by this copyright notice and the following disclaimer.
*
* THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
* GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
* TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
* STATUTORY
#define AD_SCALE 2.400f //0到4096对应外部输入电压0到10v(0~10000)
uint8_t timer100ms_updateflag = 0;
/**
* @brief this function handles timer1 overflow handler.
* @param none
* @retval none
*/
void TMR1_OVF_TMR10_IRQHandler(void)
{
if(tmr_flag_get(TMR1, TMR_OVF_FLAG) != RESET)
{
/* add user code... */
timer100ms_updateflag = 1;
tmr_flag_clear(TMR1, TMR_OVF_FLAG);
}
}
crm_clocks_freq_type crm_clocks_freq_struct = {0};
void TIM1_TimeBaseInit(void)
{
/* get system clock */
crm_clocks_freq_get(&crm_clocks_freq_struct);
/* enable tmr1 clock */
crm_periph_clock_enable(CRM_TMR1_PERIPH_CLOCK, TRUE);
/* tmr1 configuration */
/* time base configuration */
tmr_base_init(TMR1, 999, (crm_clocks_freq_struct.ahb_freq / 10000) - 1);
tmr_cnt_dir_set(TMR1, TMR_COUNT_UP);
/* overflow interrupt enable */
tmr_interrupt_enable(TMR1, TMR_OVF_INT, TRUE);
/* tmr1 overflow interrupt nvic init */
nvic_irq_enable(TMR1_OVF_TMR10_IRQn, 1, 0);
/* enable tmr1 */
tmr_counter_enable(TMR1, TRUE);
// clkout_config();
}
__IO double fatualvot[AD_NUM];
int main(void)
{
u32 chnl;
u16 ADvolt[AD_NUM];
system_clock_config();
nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
TIM1_TimeBaseInit();
App_MutiAdcCfg();
adc_ordinary_software_trigger_enable(ADC1, TRUE);
while(1)
{
if (timer100ms_updateflag)
{
timer100ms_updateflag = 0;
Get_ADValue(ADvolt);
for (chnl=0; chnl<AD_NUM; chnl++)
{
fatualvot[chnl] = AD_SCALE * ADvolt[chnl];
printf("vtmp[%d]=%d\r\n", chnl,(u16)fatualvot[chnl]);
}
}
}
}
————————————————
版权声明:本文为CSDN博主「章鱼哥嵌入式开发」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/shufawangzhang/article/details/124923691
|
|
很好的资源,学习啦~~