高级会员

- 积分
- 514
- 金钱
- 514
- 注册时间
- 2017-5-21
- 在线时间
- 82 小时
|
小弟遇到一个棘手的程序问题,我的main函数调用了另外一个.c文件里面的数据采集的子函数,然后这个子函数还调用了adc.c里的获取AD的子函数(DMA方式)。然后主函数还有调用了OLED显示的函数,发现AD值不能动态更新,屏幕要按键下翻页之后才能刷新数值。但是我如果直接在主函数中调用ADC.c里的获取AD的子函数,OLED是能动态刷新的。我的AD变量是采用结构体的方式弄的,不知道会不会是这个问题,我还是很少用结构体的,可能会有出现问题,还望大佬们指点一二。
附上部分代码:
mian.c
[mw_shl_code=c,true]PidType TemperaturePid;//PID控制器参数 该结构体在control.h中定义
SensorParameterType SensorParameter[8];//传感器参数 该结构体在collect.h中定义
ControlParameterType ControlParameter;//系统控制结构体参数 该结构体在ui.h中定义
extern PidType TemperaturePid;
extern SensorParameterType SensorParameter[8];
extern ControlParameterType ControlParameter;
for(;;)
{
ControlParameter.WorkNumTemp = ControlParameter.WorkNum;
switch(ControlParameter.WorkNum)
{
case 0://任务0 数据采集(AD) + 数据处理(滤波)
//AnalogCollcet();
AdcCollect();
// SensorParameter[0].Value = AdcDmaGetAverageValue(0);
// SensorParameter[1].Value = AdcDmaGetAverageValue(1);
// SensorParameter[2].Value = AdcDmaGetAverageValue(2);
break;
case 1://任务1 输出控制(PID) + 数据上传(UART)
//PidControl();
break;
case 2://任务2 按键
KeyControl();
break;
case 3://任务3 数据显示(oled)
UiShow();
break;
default:
break;
}
while(ControlParameter.WorkNum == ControlParameter.WorkNumTemp);//完成一次任务之后等待编号改动再执行下一个任务,防止重复执行任务
}[/mw_shl_code]
collect.c
[mw_shl_code=applescript,true]extern SensorParameterType SensorParameter[8];
void AdcCollect(void)
{
//6模拟灰度传感器+2个红外传感器
u8 i;
for(i = 0; i < 8; i++)
{
SensorParameter.Value = AdcDmaGetAverageValue(i);
}
}
[/mw_shl_code]
adc.c
[mw_shl_code=applescript,true]void AdcInit(void)//加入DMA初始化
{
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
RCC_AHBPeriphClockCmd(DmaClockCmd, ENABLE);//!!!
RCC_APB2PeriphClockCmd(AdcGpioAClockCmd |AdcGpioCClockCmd | AdcClockCmd, ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div6);//设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M
//作为模拟通道输入引脚 PA2~7
GPIO_InitStructure.GPIO_Pin = AdcPinChannel2 | AdcPinChannel3 | AdcPinChannel4 | AdcPinChannel5 | AdcPinChannel6 | AdcPinChannel7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;//模拟输入引脚
GPIO_Init(AdcGpioA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = AdcPinChannel0 | AdcPinChannel1; //PC0 PC1
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;//模拟输入引脚
GPIO_Init(AdcGpioC, &GPIO_InitStructure);
ADC_DeInit(ADC1); //复位ADC1
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作模式:ADC1和ADC2工作在独立模式
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数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = N; //顺序进行规则转换的ADC通道的数目 N !!!!
ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器
//设置指定ADC的规则组通道,设置它们的转化顺序和采样时间
//ADC1,ADC通道x,规则采样顺序值为y,采样时间为239.5周期!!!!!!!!!1
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 1, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 2, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 3, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 4, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 5, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 6, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 7, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 8, ADC_SampleTime_239Cycles5 );
DMA_DeInit(DMA1_Channel1); //将DMA的通道1寄存器重设为缺省值
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&ADC1->DR; //DMA外设ADC基地址
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&AdcConvertValue; //DMA内存基地址!!!!!!
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //内存作为数据传输的目的地
DMA_InitStructure.DMA_BufferSize = M*N; //DMA通道的DMA缓存的大小 !!!!!
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址寄存器不变
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器递增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //数据宽度为16位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //数据宽度为16位
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //工作在循环缓存模式
DMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMA通道 x拥有高优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x没有设置为内存到内存传输
DMA_Init(DMA1_Channel1, &DMA_InitStructure); //根据DMA_InitStruct中指定的参数初始化DMA的通道
DMA_Cmd(DMA1_Channel1,ENABLE);
ADC_DMACmd(ADC1, ENABLE);// 开启ADC的DMA支持(要实现DMA功能,还需独立配置DMA通道等参数)
ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1
ADC_ResetCalibration(ADC1); //使能复位校准
while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束
ADC_StartCalibration(ADC1); //开启AD校准
while(ADC_GetCalibrationStatus(ADC1)); //等待校准结束
ADC_SoftwareStartConvCmd(ADC1, ENABLE);//由于没有采用外部触发,所以使用软件触发ADC转换 !!!!!
}
u16 AdcDmaGetAverageValue(u8 ch)
{
u32 sum = 0;
u8 count;
for ( count=0;count<M;count++)
{
sum += AdcConvertValue[count][ch];
}
AdcAverageValue[ch]=sum/M;
return AdcAverageValue[ch];
}
[/mw_shl_code]
ui.c
[mw_shl_code=applescript,true]
extern PidType TemperaturePid;
extern ControlParameterType ControlParameter;
extern SensorParameterType SensorParameter[8];
OledPrintf(0,0,"%02d",ControlParameter.PageIndex+1);//显示页码
OledPrintf(32,0,"%s","Environment");//显示标题
OledPrintf(0,1,"%s","Num Val Max");//显示标题
OledPrintf(0,2,"%-4d %4d %4d",1,SensorParameter[0].Value,SensorParameter[0].Max);//显示1号灰度传感器
OledPrintf(0,3,"%-4d %4d %4d",2,SensorParameter[1].Value,SensorParameter[1].Max);//显示2号灰度传感器
OledPrintf(0,4,"%-4d %4d %4d",3,SensorParameter[2].Value,SensorParameter[2].Max);//显示3号灰度传感器
OledPrintf(0,5,"%-4d %4d %4d",4,SensorParameter[3].Value,SensorParameter[3].Max);//显示4号灰度传感器
OledPrintf(0,6,"%-4d %4d %4d",5,SensorParameter[4].Value,SensorParameter[4].Max);//显示5号灰度传感器
OledPrintf(0,7,"%-4d %4d %4d",6,SensorParameter[5].Value,SensorParameter[5].Max);//显示6号灰度传感器[/mw_shl_code]
|
|