你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32 DMA 有问题,采集数据会乱?

[复制链接]
yaoyutaoTom 提问时间:2015-5-27 14:26 /
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);
}



收藏 评论1 发布时间:2015-5-27 14:26

举报

1个回答
沐紫 回答时间:2015-5-27 17:26:00
帖子太多,容易沉,大家自己多顶顶

所属标签

相似问题

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版