STM32 DMA 有问题,采集数据会乱?
STM32F103DMA采集 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;
volatile static uint16_t pwm;
static temp_ctrl_t const temp_ctrl = {
{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;
static volatile uint8_t temp_show;
//ÈÈÃôµç×èζȱ仯ʱµÄ×èÖµ0-100¶È
const uint16_t temperature = {
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) || (res < temperature))
return -1;
while ((start + 1) < end) {
tmp = (end + start) / 2;
if (temperature == res) return tmp;
if (temperature > 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.temp_pin;
GPIO_Init(temp_ctrl.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.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);
}
#definePTC
//¿ªÆô»ò¹Ø±Õζȼì²â
void calc_temp(void)
{
uint8_t i, j;
uint16_t temp_sum;
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 = 0;
//Çó³ö10´ÎµçѹµÄºÍÖµ
for (i = 0; i < ADC_SAMPLE_NUM; i++) {
for (j = 0; j < TEMP_CHN_NUM; j++) {
temp_sum += ADC1ConvertedValue;
}
}
//ÓɵçѹµÄºÍÖµÇó³öζÈÖµ
for (i = 0; i < TEMP_CHN_NUM; i++) {
v_avg = temp_sum * 330 / 4095;//ƽ¾ùÖµÀ©´ó1000±¶
resistance = (1000 * v_avg) / (3300 - v_avg);
temp_show = search_temperature(resistance);
//ÓÉζÈÖµÇó³ö¶ÔÓ¦µÄPWMÖµ
error = target_temp - temp_show;
if (error < 0 ) {
heat_h = 0;
sum_err += error;
} else if (error < 8){
#ifdef PTC
heat_h = error * 100;
#else
sum_err += error;
sum_err *= 5;
sum_err = sum_err > 999 ? 999 : sum_err;
heat_h = (error * 90);// + sum_err;
heat_h = heat_h > 999 ? 999 : heat_h;
#endif
} else {
heat_h = 999;
}
}
if (GROUP_LOW == get_temp_group()) {
pwm = heat_h;
pwm = heat_h;
pwm = heat_h;
pwm = heat_h;
} else {
pwm = heat_h;
pwm = heat_h;
pwm = heat_h;
pwm = heat_h;
}
}
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;
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 = 0;
//Çó³ö10´ÎµçѹµÄºÍÖµ
for (i = 0; i < ADC_SAMPLE_NUM; i++) {
for (j = 0; j < TEMP_CHN_NUM; j++) {
temp_sum += ADC1ConvertedValue;
}
}
//ÓɵçѹµÄºÍÖµÇó³öζÈÖµ
for (i = 0; i < TEMP_CHN_NUM; i++) {
v_avg = temp_sum * 330 / 4095;//ƽ¾ùÖµÀ©´ó1000±¶
resistance = (1000 * v_avg) / (3300 - v_avg);
temp_show = search_temperature(resistance);
//ÓÉζÈÖµÇó³ö¶ÔÓ¦µÄPWMÖµ
error = target_temp - temperature;
if (error < 0 ) {
heat_h = 0;
} else if (error < 8){
heat_h = error * 88;
} else {
heat_h = 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 = START1;
msg.text = START2;
if (GROUP_LOW == get_temp_group()) {
msg.text = TEMP_LOW;
msg.text = temp_show;
msg.text = temp_show;
msg.text = temp_show;
msg.text = temp_show;
} else if (GROUP_HIGH == get_temp_group()){
msg.text = TEMP_HIGH;
msg.text = temp_show;
msg.text = temp_show;
msg.text = temp_show;
msg.text = temp_show;
}
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) {
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]