使用Platformio平臺的libopencm3開發(fā)框架來開發(fā)STM32G0,以下為多通道ADC與DMA的使用。
1 新建項(xiàng)目
- 建立adc_dma項(xiàng)目
在PIO的Home頁面新建項(xiàng)目,項(xiàng)目名稱adc_dma,選擇開發(fā)板為 MonkeyPi_STM32_G070RB,開發(fā)框架選擇libopencm3;
- 項(xiàng)目建立完成后在src目錄下新建main.c主程序文件;
- 修改下載和調(diào)試方式,這里開發(fā)板使用的是DAPLink仿真器,因此修改platformio.ini文件如下:
1upload_protocol = cmsis-dap
2debug_tool = cmsis-dap
2 編寫程序
2.1 ADC 設(shè)置
這里設(shè)置PA0、PA1、PA2、PA3四個(gè)引腳為ADC:
1static void adc_setup(void)
2{
3 rcc_periph_clock_enable(RCC_ADC);
4 rcc_periph_clock_enable(RCC_GPIOA);
5
6 gpio_mode_setup(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO0);
7 gpio_mode_setup(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO1);
8 gpio_mode_setup(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO2);
9 gpio_mode_setup(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO3);
10
11 adc_power_off(ADC1);
12 adc_set_clk_prescale(ADC1, ADC_CCR_PRESC_DIV2);
13 adc_set_single_conversion_mode(ADC1);
14 adc_set_right_aligned(ADC1);
15 adc_set_sample_time_on_all_channels(ADC1, ADC_SMPTIME_160DOT5);
16
17 uint8_t channel_array[16] = {0};
18 channel_array[0] = 0;
19 channel_array[1] = 1;
20 channel_array[2] = 2;
21 channel_array[3] = 3;
22 adc_set_regular_sequence(ADC1, ADC_CHAN_CNT, channel_array);
23 adc_enable_dma_circular_mode(ADC1);
24 adc_set_resolution(ADC1, ADC_CFGR1_RES_12_BIT);
25 adc_power_on(ADC1);
26
27 /* Wait for ADC starting up. */
28 delay_ms(10);
29}
2.2 DMA配置
1static void dma_setup(void *data, int size)
2{
3 dma_channel_reset(DMA1, DMA_CHANNEL1);
4 dma_set_peripheral_address(DMA1, DMA_CHANNEL1, (uint32_t)&ADC_DR(ADC1));
5 dma_set_memory_address(DMA1, DMA_CHANNEL1, (uint32_t)data);
6 dma_set_number_of_data(DMA1, DMA_CHANNEL1, size);
7 dma_set_read_from_peripheral(DMA1, DMA_CHANNEL1);
8 dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL1);
9 dma_set_peripheral_size(DMA1, DMA_CHANNEL1, DMA_CCR_PSIZE_16BIT);
10 dma_set_memory_size(DMA1, DMA_CHANNEL1, DMA_CCR_MSIZE_16BIT);
11 dma_enable_circular_mode(DMA1, DMA_CHANNEL1);
12 dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL1);
13 dma_enable_channel(DMA1, DMA_CHANNEL1);
14
15 dmamux_reset_dma_channel(DMAMUX1, DMA_CHANNEL1);
16 dmamux_set_dma_channel_request(DMAMUX1, DMA_CHANNEL1, DMAMUX_CxCR_DMAREQ_ID_ADC);
17}
主要是設(shè)置DMA的外設(shè)地址為ADC數(shù)據(jù)寄存器 ADC_DR;并設(shè)置內(nèi)存地址為定義的buff,size為需要緩存的數(shù)據(jù)大?。?/p>
1#define ADC_CHAN_CNT 4
2#define ADC_FILETER_SIZE 32
3
4int16_t adc_values[ADC_FILETER_SIZE*ADC_CHAN_CNT];
2.3 ADC配置為DMA讀取和Timer觸發(fā)
- 定時(shí)器設(shè)置
1void tim3_setup(void)
2{
3 /* Enable TIM3 clock. */
4 rcc_periph_clock_enable(RCC_TIM3);
5
6 /* Enable TIM3 interrupt. */
7 nvic_enable_irq(NVIC_TIM3_IRQ);
8
9 /* Reset TIM3 peripheral to defaults. */
10 rcc_periph_reset_pulse(RST_TIM3);
11
12 /* Timer global mode:
13 * - No divider
14 * - Alignment edge
15 * - Direction up
16 * (These are actually default values after reset above, so this call
17 * is strictly unnecessary, but demos the api for alternative settings)
18 */
19 timer_set_mode(TIM3, TIM_CR1_CKD_CK_INT,
20 TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
21
22 /*
23 * Please take note that the clock source for STM32 timers
24 * might not be the raw APB1/APB2 clocks. In various conditions they
25 * are doubled. See the Reference Manual for full details!
26 * In our case, TIM3 on APB1 is running at double frequency, so this
27 * sets the prescaler to have the timer run at 5kHz
28 */
29 timer_set_prescaler(TIM3, 64-1);
30
31 /* Disable preload. */
32 timer_disable_preload(TIM3);
33 timer_continuous_mode(TIM3);
34
35 timer_set_period(TIM3, 20000-1); //100Hz
36
37 timer_set_master_mode(TIM3, TIM_CR2_MMS_UPDATE);
38
39 timer_enable_irq(TIM3, TIM_DIER_UIE);
40}
41
42void tim3_enable_counter(bool en)
43{
44 if(en){
45 timer_enable_counter(TIM3);
46 }else{
47 timer_disable_counter(TIM3);
48 }
49}
50
51void tim3_isr(void)
52{
53 if (timer_get_flag(TIM3, TIM_SR_UIF)) {
54
55 /* Clear compare interrupt flag. */
56 timer_clear_flag(TIM3, TIM_SR_UIF);
57 }
58}
- DMA設(shè)置和Timer觸發(fā)
1 rcc_periph_clock_enable(RCC_DMA);
2 nvic_set_priority(NVIC_DMA1_CHANNEL1_IRQ, 3);
3 nvic_enable_irq(NVIC_DMA1_CHANNEL1_IRQ);
4
5 adc_setup();
6
7 dma_setup(adc_values, ADC_CHAN_CNT*ADC_FILETER_SIZE);
8
9 adc_enable_overrun_interrupt(ADC1);
10
11 adc_enable_dma(ADC1);
12
13 ADC_CFGR1(ADC1) = (ADC_CFGR1(ADC1) & ~(0x3<<10)) | (0x1<<10); // Hardware trigger detection on the rising edge
14 ADC_CFGR1(ADC1) = (ADC_CFGR1(ADC1) & ~ADC_CFGR1_EXTSEL) | (3<1_EXTSEL_SHIFT); // toggle by tim3
15
16 tim3_setup();
17
18 adc_start_conversion_regular(ADC1);
19
20
21 tim3_enable_counter(true);
22
23 delay_ms(100);
DMA中斷時(shí)候即準(zhǔn)備好讀取ADC數(shù)據(jù),因此在DMA中斷中先把定時(shí)器關(guān)閉,讀取數(shù)據(jù)后再次打開:
1void dma1_channel1_isr(void)
2{
3
4 if ((DMA1_ISR &DMA_ISR_TCIF1) != 0) {
5 DMA1_IFCR |= DMA_IFCR_CTCIF1;
6 }
7
8 tim3_enable_counter(false);
9
10}
2.4 ADC讀取
1void adc_sample(void)
2{
3 uint32_t sum_val1 = 0;
4 uint32_t sum_val2 = 0;
5 uint32_t sum_val3 = 0;
6 uint32_t sum_val4 = 0;
7
8 for(int i=0; i9 sum_val1 += adc_values[ADC_CHAN_CNT*i + 0];
10 sum_val2 += adc_values[ADC_CHAN_CNT*i + 1];
11 sum_val3 += adc_values[ADC_CHAN_CNT*i + 2];
12 sum_val4 += adc_values[ADC_CHAN_CNT*i + 3];
13 }
14
15 uint32_t filter_val1 = sum_val1/ADC_FILETER_SIZE;
16 uint32_t filter_val2 = sum_val2/ADC_FILETER_SIZE;
17 uint32_t filter_val3 = sum_val3/ADC_FILETER_SIZE;
18 uint32_t filter_val4 = sum_val4/ADC_FILETER_SIZE;
19
20 printf("adc:%d %d %d %d\\r\\n", filter_val1, filter_val2, filter_val3, filter_val4);
21
22 tim3_enable_counter(true);
23}
讀取時(shí)候按照通道的順序從buff中取出,這里做了簡單的過濾;
3 燒寫測試
將程序燒寫到開發(fā)板,然后打開串口可以看到四個(gè)ADC通道的數(shù)據(jù),在PA0/PA1/PA3/PA4四個(gè)引腳連接不同電壓可以看到變化:
-
寄存器
+關(guān)注
關(guān)注
31文章
5433瀏覽量
124335 -
adc
+關(guān)注
關(guān)注
99文章
6688瀏覽量
549088 -
STM32
+關(guān)注
關(guān)注
2293文章
11031瀏覽量
364489 -
dma
+關(guān)注
關(guān)注
3文章
576瀏覽量
103151 -
PIO
+關(guān)注
關(guān)注
0文章
20瀏覽量
6421
發(fā)布評論請先 登錄
stm32 定時(shí)器觸發(fā)ADC多通道采樣+DMA提取數(shù)據(jù)相關(guān)資料下載
stm32 定時(shí)器觸發(fā)ADC多通道采樣+DMA提取數(shù)據(jù)

STM32G0開發(fā)筆記:FreeRTOS和FreeModbus庫使用

STM32G0開發(fā)筆記:FreeRTOS和CLI組件使用

STM32G0開發(fā)筆記:使用FreeRTOS系統(tǒng)的隊(duì)列Queue
STM32G0開發(fā)筆記:使用FreeRTOS系統(tǒng)

STM32G0開發(fā)筆記:使用ADC進(jìn)行NTC溫度采集

STM32G0開發(fā)筆記:用PWM來實(shí)現(xiàn)LED呼吸燈效果

STM32G0開發(fā)筆記:EEPROM M24C02的使用方法

STM32G0開發(fā)筆記:串口中斷的使用
STM32G0開發(fā)筆記:GPIO接按鍵的使用方式
STM32G0開發(fā)筆記:使用libopencm3庫

評論