STM32F103 DMA采集 8路AD,AD为温度检测,10K的热敏电阻,上拉1K至3.3V, 检测到电压时,转为电阻值,通过电阻值二分查找温度,大部分情况下都没有问题,10中有一次,会出现温度错位。即通道2显示的是通过0的温度,通道4显示的是通过2的温度?代码如下: #include "stdint.h" #include "stm32f10X_gpio.h" #include "stm32f10x_dma.h" #include "stm32f10x_adc.h" #include "temperature.h" #include "queue.h" #include "gui.h" #include "pid.h" #define ADC_SAMPLE_NUM (10) #define ADC_BUF_SIZE (ADC_SAMPLE_NUM * TEMP_CHN_NUM) #define ADC1_DR_Address ((uint32_t)0x4001244C) typedef struct { GPIO_TypeDef* temp_port; uint16_t temp_pin; uint8_t ADC_Channel; temp_grp_t group; } temp_ctrl_t; //µ±Ç°Î¶ȵÄ״̬£¬¹Ø±Õ»ò´ò¿ª static volatile temp_state_t temp_sta; //µ±Ç°É趨µÄÄ¿±êÎÂ¶È static volatile uint8_t target_temp = 60; //µ±Ç°µÄ¼ÓÈÈ×飬LOWΪ0 2 4 6¼ÓÈÈͨµÀ£¬HIGHΪ1£¬ 3 5 7¼ÓÈÈͨµÀ static volatile temp_grp_t temp_grp; //ζÈÊä³öµÄpwm volatile static int16_t heat_h[TEMP_CHN_NUM]; volatile static uint16_t pwm[GROUP_LENGTH]; static temp_ctrl_t const temp_ctrl[TEMP_CHN_NUM] = { {GPIOA, GPIO_Pin_0, ADC_Channel_0, GROUP_LOW}, {GPIOA, GPIO_Pin_1, ADC_Channel_1, GROUP_HIGH}, {GPIOA, GPIO_Pin_2, ADC_Channel_2, GROUP_LOW}, {GPIOA, GPIO_Pin_3, ADC_Channel_3, GROUP_HIGH}, {GPIOA, GPIO_Pin_4, ADC_Channel_4, GROUP_LOW}, {GPIOA, GPIO_Pin_5, ADC_Channel_5, GROUP_HIGH}, {GPIOA, GPIO_Pin_6, ADC_Channel_6, GROUP_LOW}, {GPIOA, GPIO_Pin_7, ADC_Channel_7, GROUP_HIGH} }; static volatile uint16_t ADC1ConvertedValue[ADC_SAMPLE_NUM][TEMP_CHN_NUM]; static volatile uint8_t temp_show[TEMP_CHN_NUM]; //ÈÈÃôµç×èζȱ仯ʱµÄ×èÖµ0-100¶È const uint16_t temperature[150] = { 32485, 30870, 29346, 27934, 26580, 25298, 24086, 22938, 21851, 20822, 19847, 18923, 18047, 17216, 16428, 15680, 14971, 14297, 13658, 13050, 12473, 11924, 11402, 10906, 10434, 10000, 9558, 9152, 8764, 8396, 8044, 7709, 7390, 7086, 6796, 6519, 6255, 6003, 5762, 5533, 5314, 5104, 4904, 4713, 4530, 4355, 4187, 4027, 3874, 3728, 3588, 3454, 3326, 3203, 3086, 2973, 2865, 2762, 2662, 2567, 2476, 2389, 2305, 2224, 2147, 2072, 2001, 1933, 1867, 1803, 1743, 1684, 1628, 1574, 1522, 1470, 1424, 1378, 1333, 1290, 1249, 1209, 1171, 1134, 1099, 1064, 1031, 999, 968, 935, 907, 879, 854, 828, 804, 780, 757, 736, 714, 694, 674, 655, 636, 619, 601, 584, 568, 553, 538, 523, 509, 495, 482, 469, 457, 445, 433, 421, 410, 400, 390, 380, 370, 361, 352, 343, 335, 326, 318, 310, 303, 295, 291, 284, 277, 270, 264, 257, 251, 245, 239, 233, 228, 223, 217, 212, 208, 203, 198, 194 }; //ÉèÖôò¿ª»ò¹Ø±Õ¼ÓÈÈÄ£¿é void set_temp_state(volatile temp_state_t state) { temp_sta = state; } temp_state_t get_temp_state(void) { return temp_sta; } //ÉèÖüÓÈÈ×é void set_temp_group(temp_grp_t grp) { temp_grp = grp; } temp_grp_t get_temp_group(void) { return temp_grp; } /* ÃèÊö£º¸ù¾Ýµç×èÖµ£¬²éÕÒÏàÓ¦µÄζ res: Ϊµç×èÖµ rvl: ·µ»ØÏàÓ¦µÄÎÂ¶È */ static int search_temperature(uint16_t res) { uint8_t start = 0, end = 149; uint8_t tmp; if ((res > temperature[start]) || (res < temperature[end])) return -1; while ((start + 1) < end) { tmp = (end + start) / 2; if (temperature[tmp] == res) return tmp; if (temperature[tmp] > res) { start = tmp; } else { end = tmp; } } return start; } static void GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; uint8_t i; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE); for (i = 0; i < TEMP_CHN_NUM; i++) { GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_InitStructure.GPIO_Pin = temp_ctrl[i].temp_pin; GPIO_Init(temp_ctrl[i].temp_port, &GPIO_InitStructure); } } static void dma_init() { /* DMA1 channel1 configuration ----------------------------------------------*/ DMA_InitTypeDef DMA_InitStructure; DMA_DeInit(DMA1_Channel1); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC1ConvertedValue; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = ADC_BUF_SIZE; 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_High; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel1, &DMA_InitStructure); //DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE); } static void adc_init() { uint8_t i; /* ADC1 configuration ------------------------------------------------------*/ ADC_InitTypeDef ADC_InitStructure; RCC_ADCCLKConfig(RCC_PCLK2_Div6); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2, ENABLE); ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; if (1 == TEMP_CHN_NUM) ADC_InitStructure.ADC_ScanConvMode = DISABLE; else 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 = TEMP_CHN_NUM; ADC_Init(ADC1, &ADC_InitStructure); /* ADC1 regular channels configuration */ for (i = 0; i < TEMP_CHN_NUM; i++) ADC_RegularChannelConfig(ADC1, temp_ctrl[i].ADC_Channel, i + 1, ADC_SampleTime_41Cycles5); ADC_DMACmd(ADC1, ENABLE); /* Enable ADC1 */ ADC_Cmd(ADC1, ENABLE); /* Enable ADC1 reset calibration register */ ADC_ResetCalibration(ADC1); /* Check the end of ADC1 reset calibration register */ while(ADC_GetResetCalibrationStatus(ADC1)); /* Start ADC1 calibration */ ADC_StartCalibration(ADC1); /* Check the end of ADC1 calibration */ while(ADC_GetCalibrationStatus(ADC1)); /* Enable DMA1 channel1 */ DMA_Cmd(DMA1_Channel1, ENABLE); ADC_SoftwareStartConvCmd(ADC1, ENABLE); } #define PTC //¿ªÆô»ò¹Ø±Õζȼì²â void calc_temp(void) { uint8_t i, j; uint16_t temp_sum[TEMP_CHN_NUM]; uint16_t v_avg, resistance; int8_t error; static int16_t sum_err = 0; //°ÑÇóÖµµÄÊý×é³õʼΪ0 for (i = 0; i < TEMP_CHN_NUM; i++) temp_sum[i] = 0; //Çó³ö10´ÎµçѹµÄºÍÖµ for (i = 0; i < ADC_SAMPLE_NUM; i++) { for (j = 0; j < TEMP_CHN_NUM; j++) { temp_sum[j] += ADC1ConvertedValue[i][j]; } } //ÓɵçѹµÄºÍÖµÇó³öζÈÖµ for (i = 0; i < TEMP_CHN_NUM; i++) { v_avg = temp_sum[i] * 330 / 4095; //ƽ¾ùÖµÀ©´ó1000±¶ resistance = (1000 * v_avg) / (3300 - v_avg); temp_show[i] = search_temperature(resistance); //ÓÉζÈÖµÇó³ö¶ÔÓ¦µÄPWMÖµ error = target_temp - temp_show[i]; if (error < 0 ) { heat_h[i] = 0; sum_err += error; } else if (error < 8){ #ifdef PTC heat_h[i] = error * 100; #else sum_err += error; sum_err *= 5; sum_err = sum_err > 999 ? 999 : sum_err; heat_h[i] = (error * 90);// + sum_err; heat_h[i] = heat_h[i] > 999 ? 999 : heat_h[i]; #endif } else { heat_h[i] = 999; } } if (GROUP_LOW == get_temp_group()) { pwm[0] = heat_h[0]; pwm[1] = heat_h[2]; pwm[2] = heat_h[4]; pwm[3] = heat_h[6]; } else { pwm[0] = heat_h[1]; pwm[1] = heat_h[3]; pwm[2] = heat_h[5]; pwm[3] = heat_h[7]; } } void set_temp(uint8_t temperature) { target_temp = temperature; } void temperature_init(void) { GPIO_Configuration(); dma_init(); adc_init(); set_temp_state(TEMP_CLOSE); set_temp_group(GROUP_LOW); } /* void DMA1_Channel1_IRQHandler(void) { uint8_t i, j; uint16_t temp_sum[TEMP_CHN_NUM]; uint16_t v_avg, resistance; int8_t error; if(DMA_GetITStatus(DMA1_IT_TC1) != RESET) { //°ÑÇóÖµµÄÊý×é³õʼΪ0 for (i = 0; i < TEMP_CHN_NUM; i++) temp_sum[i] = 0; //Çó³ö10´ÎµçѹµÄºÍÖµ for (i = 0; i < ADC_SAMPLE_NUM; i++) { for (j = 0; j < TEMP_CHN_NUM; j++) { temp_sum[j] += ADC1ConvertedValue[i][j]; } } //ÓɵçѹµÄºÍÖµÇó³öζÈÖµ for (i = 0; i < TEMP_CHN_NUM; i++) { v_avg = temp_sum[i] * 330 / 4095; //ƽ¾ùÖµÀ©´ó1000±¶ resistance = (1000 * v_avg) / (3300 - v_avg); temp_show[i] = search_temperature(resistance); //ÓÉζÈÖµÇó³ö¶ÔÓ¦µÄPWMÖµ error = target_temp - temperature[i]; if (error < 0 ) { heat_h[i] = 0; } else if (error < 8){ heat_h[i] = error * 88; } else { heat_h[i] = 999; } } DMA_ClearITPendingBit(DMA1_IT_GL1); } } */ #define TEMP_LOW 0X54 #define TEMP_HIGH 0X55 //ÏòÉÏλ»ú´«ËÍ£¬¼ì²âµ½µÄζÈÖµ£¬¹²ÓÐ4· void do_send_temp(void) { msg_t msg; msg.text[0] = START1; msg.text[1] = START2; if (GROUP_LOW == get_temp_group()) { msg.text[2] = TEMP_LOW; msg.text[3] = temp_show[0]; msg.text[4] = temp_show[2]; msg.text[5] = temp_show[4]; msg.text[6] = temp_show[6]; } else if (GROUP_HIGH == get_temp_group()){ msg.text[2] = TEMP_HIGH; msg.text[3] = temp_show[1]; msg.text[4] = temp_show[3]; msg.text[5] = temp_show[5]; msg.text[6] = temp_show[7]; } put_msg(msg); } void heat_output(volatile uint16_t cnt) { uint8_t i; if (TEMP_CLOSE == get_temp_state()) { heat_all_off(); return; } for (i = 0; i < GROUP_LENGTH; i++) { if (cnt < pwm[i]) { heat_on(get_temp_group(), i); } else { heat_off(get_temp_group(), i); } } } #include "stdint.h" #include "systick.h" #include "soft_timer.h" #include "queue.h" #include "temperature.h" #include "speaker.h" #include "gui.h" static volatile uint32_t time_delay; static volatile uint16_t sec; static volatile uint16_t time_int; void SysTick_Handler(void) { static uint16_t systick_cnt = 0; volatile sig_t sig; if (time_delay != 0x00) { time_delay--; } spk_beep(); if (999 == systick_cnt) { systick_cnt = 0; if (sec != 0x00) { sec--; } calc_temp(); do_send_temp(); if (SOFT_TIMER_RUN == get_softtimer_state()) { if (0 != get_softtimer_time()) { softtimer_process(); sig = SIG_TIME_SEC_INT; put_sig(sig); } else { softtimer_stop(); sig = SIG_TIME_END; put_sig(sig); } } } else { systick_cnt++; heat_output(systick_cnt); } } void set_sec(uint16_t s) { sec = s; } uint16_t get_sec(void) { return sec; } void delay_ms(uint16_t ms) { time_delay = ms; while (time_delay != 0); } |
帖子太多,容易沉,大家自己多顶顶 |