开启DMA后,程序无法启动
各位大侠好:小弟新学32,编了个测8路数据的程序,其他都还正常。就是当开启使用ADC1的DMA1后,程序编译下载后就无法启动,小弟照着手册例程改了好多遍仍旧无法启动。没办法了,在这向各位大侠请教!!请各位大侠看看,小弟感激不尽,如要程序截图和调试截图都可以奉上,谢谢了!!!楼主程序可以公开吗?贴程序看下吧,这么说看不出什么原因
Reset_Handler PROC
EXPORTReset_Handler
IMPORT__main
IMPORTSystemInit
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0 //单步调试程序卡在这里,下不去了
ENDP 把主函数代码贴出来 如果确定是ADC1/DMA引起的问题,
会不会是访问对齐、越界方面的原因?
肯定是配置的问题,至于是哪里,就动了哪里了
哪位大侠能帮助小弟找到原因小弟感激不尽,下面是程序截图://这是ADC部分,其中:GetADCValue()函数在TIM3中断中调用,用以读出转换值:
void ADCInit(void) //初始化ADC
{ unsigned char t;
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDefADC_InitStructure;
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC时钟分频系数,ADC时钟最大不超过14M
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1|
RCC_APB2Periph_GPIOA, ENABLE);//开启ADC1和GPIOA时钟
//初始化ADC对应的GPIO口
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3|
GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化ADC1对应的GPIO口
//ADC1设置
ADC_DeInit(ADC1);//复位ADC外设寄存器.
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //独立模式
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 = 8; //8通道
ADC_Init(ADC1, &ADC_InitStructure); //初始化设置
ADC_DMACmd(ADC1, ENABLE); //使能ADC1对应的DMA
ADC_Cmd(ADC1, ENABLE); //使能ADC1
ADC_ResetCalibration(ADC1); //复位ADC校准寄存器
while(ADC_GetResetCalibrationStatus(ADC1)); //等待ADC1校准寄存器复位
ADC_StartCalibration(ADC1); //开始校准ADC1
while(ADC_GetCalibrationStatus(ADC1)); //等待校准完成
// 指定ADC1规则组通道号,顺序及采样周期
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1,ADC_SampleTime_41Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2,ADC_SampleTime_41Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3,ADC_SampleTime_41Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4,ADC_SampleTime_41Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 5,ADC_SampleTime_41Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 6,ADC_SampleTime_41Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 7,ADC_SampleTime_41Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 8,ADC_SampleTime_41Cycles5);
for(t=0;t<8;t++)
{
CH_ADCValue=0;
CH8_MinADC=0;
CH8_MaxADC=0;
CH_ADC1TSum=0;
CH_Adc_1TAverage=0;
CH8_Id=0;
CH8_Temp=0;
CH_ADC50TSum=0;
CH_Adc_50TAverage=0;
}
ADCCnt=0;
Adc_TCnt=0;
IsStartAdjTable=0;
}
void GetADCValue(void)//得到8通道ADC数据
{ DMA_InitTypeDef DMA_InitStructure;
ADC_SoftwareStartConvCmd(ADC1,ENABLE); //开启AD转换
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待AD装换结束
DMA_Cmd(DMA1_Channel1, DISABLE); //关闭DMA_CHx所指示的通道
DMA_InitStructure.DMA_PeripheralBaseAddr =(u32)&ADC1->DR;//DMA外设ADC基地址
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&CH_ADCValue;//DMA内存基地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//数据传输方向,从外设读到内存
DMA_InitStructure.DMA_BufferSize = 8;//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_Medium; //DMA通道 x拥有中优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//DMA通道x没有设置为内存到内存传输
DMA_Init(DMA1_Channel1, &DMA_InitStructure);//根据DMA_InitStruct中指定的参数初始化DMA的通道USART1_Tx_DMA_Channel所标识的寄存器
DMA_Cmd(DMA1_Channel1, ENABLE);
if(DMA_GetFlagStatus(DMA1_FLAG_TC1)!=RESET)//等待通道1传输完成
{
ADC_Cmd(ADC1, DISABLE);//关闭ADC转换
BackCH_ADCValue=CH_ADCValue; //将ADC数据暂存出来
BackCH_ADCValue=CH_ADCValue;
BackCH_ADCValue=CH_ADCValue;
BackCH_ADCValue=CH_ADCValue;
BackCH_ADCValue=CH_ADCValue;
BackCH_ADCValue=CH_ADCValue;
BackCH_ADCValue=CH_ADCValue;
BackCH_ADCValue=CH_ADCValue;
ADC_Cmd(ADC1,ENABLE);//关闭ADC转换
DMA_ClearFlag(DMA1_FLAG_TC1);//清除通道1 传输完成标志
++ADCCnt; //当前采样次数
}
}
//这个是在主函数中对DMA的初始化:
int main(void)
{
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
TIM3_Int_Init(224,99);//定时时间为:20mS/64 (us)
AT24CXX_Init();
while(RTCInit(2018,06,18,23,17,00)) //如果时钟初始化失败则停止运行
{
SetLedDisp(DISP_E,DISP_R,DISP_R,DISP_0,DISP_0,DISP_1);
}
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE);
//改变指定管脚映射 GPIO_Remap_SWJ_JTAGDisable ,JTAG-DP 禁用 + SW-DP 使能
ADCInit(); //初始化ADC
InitDMA_Config(DMA1_Channel1,(u32)&ADC1->DR,(u32)&CH_ADCValue,8); //初始化DMA
SysParamInit();
DispAllInit();
DispProvision();
KeyInit(); //按键初始化;
MenuInit();
DoInit();
BeepInit();//初始化Beep
DIInit(); //DI初始化
while(AT24CXX_Check()) //检测不到AT24C04
{
SetLedDisp(DISP_E,DISP_R,DISP_R,DISP_0,DISP_0,DISP_2);
}
uart_init(BackMenuData.Conn_Add,BackMenuData.Conn_Baud); //串口初始化为9600
delay_ms(2000); //等待2S
while(1)
{
Rcv_End_Disposal();
MenuDispFromKey(); //根据按键显示对应菜单
DoMenuStart(MenuData.DO_Type);
DIMenuStart(MenuData.DI_type);
BeepMenuStart(MenuData.Beep_Type);
Adc_1SAverage(); //计算ADC值.
}
}
其中InitDMA_Config函数定义如下:
u16 DMA1_MEM_LEN; //表示DMA每次传输数据长度
void InitDMA_Config(DMA_Channel_TypeDef* DMA_CHx,u32 DMA_Addr,u32 Mem_Addr,u16 DMA_Buffer)
//参数1:DMA通道号; DMA_Addr:DMA基地址;Mem_Addr:内存基地址;DMA_Buffer:DMA通道的DMA缓存的大小
{ DMA_InitTypeDef DMA_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //开启DMA时钟
DMA_DeInit(DMA_CHx); //将DMA的通道1寄存器重设为缺省值
DMA1_MEM_LEN=DMA_Buffer;
DMA_InitStructure.DMA_PeripheralBaseAddr =DMA_Addr;//DMA外设ADC基地址
DMA_InitStructure.DMA_MemoryBaseAddr = Mem_Addr;//DMA内存基地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//数据传输方向,从外设读到内存
DMA_InitStructure.DMA_BufferSize = DMA_Buffer;//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_Medium; //DMA通道 x拥有中优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//DMA通道x没有设置为内存到内存传输
DMA_Init(DMA_CHx, &DMA_InitStructure);//根据DMA_InitStruct中指定的参数初始化DMA的通道USART1_Tx_DMA_Channel所标识的寄存器
} 话说我真的看不懂汇编
我也看不懂,郁闷啊!!想不通我只是开启了DMA怎么程序就不运行了???,把ADC采样部分注释掉。程序立马好了!!无语啊
是不是数据传输太长卡死了?
太复杂了,搞一堆DMA。
不是,刚测试了,只开了一个通道,还是不运行,郁闷
为了测试,开始写得很简单,不行,所以重写一遍,写得很详细,看是不是哪里漏了。结果还是不行,哎
看你的代码。主函数main都没进去,配置有问题吧。
配置应该没问题吧?对了,我今天将AdC1,和DMA1的启动放在了初始化中, GetADCValue中只保存数据,结果可以启动了,但读的数据不对。但是不明白为什么不能再中断中启动DMA( GetADCValue,函数放在TIM3中断函数中的)
void GetADCValue(void)//得到8通道ADC数据
{
BackCH_ADCValue=CH_ADCValue; //将ADC数据暂存出来
BackCH_ADCValue=CH_ADCValue;
BackCH_ADCValue=CH_ADCValue;
BackCH_ADCValue=CH_ADCValue;
BackCH_ADCValue=CH_ADCValue;
BackCH_ADCValue=CH_ADCValue;
BackCH_ADCValue=CH_ADCValue;
BackCH_ADCValue=CH_ADCValue;
IsADCNew=1; //当前单次采样完成标志
} 现在解决了吗?
谢谢询问!现在我ADC和DMA都用自动循环方式,定时器中断里只保留传过来的数据,不开关ADC和DMA,可以了
不过,现在处理ADC数据时,又遇到了一些问题,算出来的结果和实际不对,浮点数方面的。我先查查不行还得向各位大侠请教
我再好好缕一缕吧,有了好消息及时通知大家
页:
[1]