|
我使用双ADC+双DMA,一个ADC对应一个DMA,定时器使用TIM1的1、2通道分别触发,1通道对应ADC1,2通道对应ADC3,但是有一个DMA进不了中断,不知道是什么问题,但是注释掉TIM1的1通道开启,ADC3+DMA正常,注释掉TIM1的2通道开启,ADC1+DMA正常,请问怎么回事呢?程序如下:
主函数:
//定义变量
u16 ADC1_DMA_Buf[3]; //ADC1接受DMA传输的缓冲区
u16 ADC3_DMA_Buf[3]; //ADC2接受DMA传输的缓冲区
float Acceleration[2]; //加速度数组
u8 Acceleration_String_1[32];
u8 Acceleration_String_2[32];
float Speed[2]; //速度数组
u8 Speed_String_1[32];
u8 Speed_String_2[32];
float Displacement[2]; //位移数组
u8 Displacement_String_1[32];
u8 Displacement_String_2[32];
//ADC1
void DMA1_Stream0_IRQHandler(void)
{
SCB_InvalidateDCache(); //使 D-cache 无效,即CPU读取数据时,忽略 D-cache 中的内容,去真实的物理地址读取对应的数据(DMA-SRAM)。
if( __HAL_DMA_GET_FLAG(&DMA1_Stream0_Handler,DMA_FLAG_TCIF0_4)!=RESET)
{
Acceleration[0] = (float)(ADC1_DMA_Buf[0] * 3.3 / 65536);
Speed[0] = (float)(ADC1_DMA_Buf[1] * 3.3 / 65536);
Displacement[0] = (float)(ADC1_DMA_Buf[2] * 3.3 / 65536);
sprintf((char*)Acceleration_String_1,"Acceleration:%10.3lf",Acceleration[0]);
sprintf((char*)Speed_String_1,"Speed:%10.3lf",Speed[0]);
sprintf((char*)Displacement_String_1,"Displacement:%10.3lf",Displacement[0]);
LCD_ShowString(10,40,1023,32,32,Acceleration_String_1);
LCD_ShowString(10,80,1023,32,32,Speed_String_1);
LCD_ShowString(10,120,1023,32,32,Displacement_String_1);
__HAL_DMA_CLEAR_FLAG(&DMA1_Stream0_Handler,DMA_FLAG_TCIF0_4);
}
}
//ADC3
void DMA1_Stream1_IRQHandler(void)
{
SCB_InvalidateDCache(); //使 D-cache 无效,即CPU读取数据时,忽略 D-cache 中的内容,去真实的物理地址读取对应的数据(DMA-SRAM)。
if( __HAL_DMA_GET_FLAG(&DMA1_Stream1_Handler,DMA_FLAG_TCIF1_5)!=RESET)
{
Acceleration[1] = (float)(ADC3_DMA_Buf[0] * 3.3 / 65536);
Speed[1] = (float)(ADC3_DMA_Buf[1] * 3.3 / 65536);
Displacement[1] = (float)(ADC3_DMA_Buf[2] * 3.3 / 65536);
sprintf((char*)Acceleration_String_2,"Acceleration:%10.3lf",Acceleration[1]);
sprintf((char*)Speed_String_2,"Speed:%10.3lf",Speed[1]);
sprintf((char*)Displacement_String_2,"Displacement:%10.3lf",Displacement[1]);
LCD_ShowString(10,160,1023,32,32,Acceleration_String_2);
LCD_ShowString(10,200,1023,32,32,Speed_String_2);
LCD_ShowString(10,240,1023,32,32,Displacement_String_2);
__HAL_DMA_CLEAR_FLAG(&DMA1_Stream1_Handler,DMA_FLAG_TCIF1_5);
}
}
int main(void)
{
Cache_Enable(); //打开Cache
HAL_Init(); //初始化HAL库
Stm32_Clock_Init(160,5,2,4); //设置时钟 400MHZ
SDRAM_Init(); //初始化SDRAM
delay_init(400); //延时初始化
uart_init(115200); //串口初始化
LED_Init();
KEY_Init(); //初始化按键
//显示屏初始化
LCD_Init();
LCD_Clear(BLACK);
POINT_COLOR=RED;
//ADC、DMA、TIMER初始化
DMA_Init();
ADC_Init();
TIM1_PWM_Init(19999,9999);
HAL_ADC_Start_DMA(&ADC1_Handler,(uint32_t *)&ADC1_DMA_Buf,3);
HAL_ADC_Start_DMA(&ADC3_Handler,(uint32_t *)&ADC3_DMA_Buf,3);
while(1)
{
}
}
ADC:
ADC_HandleTypeDef ADC1_Handler; //ADC1句柄
ADC_HandleTypeDef ADC3_Handler; //ADC2句柄
//初始化ADC
void ADC1_Init(void)
{
ADC_ChannelConfTypeDef ADC1_Channel_Handler; //ADC2通道配置句柄
//ADC1初始化
ADC1_Handler.Instance=ADC1;
HAL_ADC_DeInit(&ADC1_Handler);
ADC1_Handler.Init.ClockPrescaler=ADC_CLOCK_SYNC_PCLK_DIV2; //同步时钟 不能打开ADC2的校准
ADC1_Handler.Init.Resolution=ADC_RESOLUTION_16B; //16位模式
ADC1_Handler.Init.ScanConvMode=ENABLE; //扫描模式
ADC1_Handler.Init.EOCSelection=ADC_EOC_SINGLE_CONV; //EOC全部转换完成进入中断
ADC1_Handler.Init.LowPowerAutoWait=DISABLE; //自动低功耗关闭
ADC1_Handler.Init.ContinuousConvMode=DISABLE; //关闭连续转换
ADC1_Handler.Init.NbrOfConversion=3; //3个转换在规则序列中
ADC1_Handler.Init.DiscontinuousConvMode=DISABLE; //禁止不连续采样模式
ADC1_Handler.Init.NbrOfDiscConversion=0; //不连续采样通道数为0
ADC1_Handler.Init.ExternalTrigConv=ADC_EXTERNALTRIG_T1_CC1; //定时器触发 TIME3-CH4
ADC1_Handler.Init.ExternalTrigConvEdge=ADC_EXTERNALTRIGCONVEDGE_RISING; //外部上升沿触发
ADC1_Handler.Init.BoostMode=ENABLE; //BOOT模式使能 时钟高于20MHz时 必须使能此位
ADC1_Handler.Init.Overrun=ADC_OVR_DATA_OVERWRITTEN; //有新的数据的后直接覆盖掉旧数据
ADC1_Handler.Init.OversamplingMode=DISABLE; //过采样关闭
ADC1_Handler.Init.ConversionDataManagement=ADC_CONVERSIONDATA_DMA_CIRCULAR; //DMA循环接受数据
HAL_ADC_Init(&ADC1_Handler); //初始化
//ADC1-Channel-16
ADC1_Channel_Handler.Channel=16; //通道 PA0
ADC1_Channel_Handler.Rank=ADC_REGULAR_RANK_1; //序列1
ADC1_Channel_Handler.SamplingTime=ADC_SAMPLETIME_2CYCLES_5; //采样周期
ADC1_Channel_Handler.SingleDiff=ADC_SINGLE_ENDED; //单边采集
ADC1_Channel_Handler.OffsetNumber=ADC_OFFSET_NONE;
ADC1_Channel_Handler.Offset=0;
HAL_ADC_ConfigChannel(&ADC1_Handler,&ADC1_Channel_Handler); //通道配置
//ADC1-Channel-19
ADC1_Channel_Handler.Channel=19; //通道 PA5
ADC1_Channel_Handler.Rank=ADC_REGULAR_RANK_2; //序列2
ADC1_Channel_Handler.SamplingTime=ADC_SAMPLETIME_2CYCLES_5; //采样周期
ADC1_Channel_Handler.SingleDiff=ADC_SINGLE_ENDED; //单边采集
ADC1_Channel_Handler.OffsetNumber=ADC_OFFSET_NONE;
ADC1_Channel_Handler.Offset=0;
HAL_ADC_ConfigChannel(&ADC1_Handler,&ADC1_Channel_Handler); //通道配置
//ADC1-Channel-3
ADC1_Channel_Handler.Channel=3; //通道 PA6
ADC1_Channel_Handler.Rank=ADC_REGULAR_RANK_3; //序列3
ADC1_Channel_Handler.SamplingTime=ADC_SAMPLETIME_2CYCLES_5; //采样周期
ADC1_Channel_Handler.SingleDiff=ADC_SINGLE_ENDED; //单边采集
ADC1_Channel_Handler.OffsetNumber=ADC_OFFSET_NONE;
ADC1_Channel_Handler.Offset=0;
HAL_ADC_ConfigChannel(&ADC1_Handler,&ADC1_Channel_Handler); //通道配置
HAL_ADCEx_Calibration_Start(&ADC1_Handler,ADC_CALIB_OFFSET,ADC_SINGLE_ENDED); //ADC校准
}
void ADC3_Init(void)
{
ADC_ChannelConfTypeDef ADC3_Channel_Handler; //ADC2通道配置句柄
//ADC2初始化
ADC3_Handler.Instance=ADC3;
HAL_ADC_DeInit(&ADC3_Handler);
ADC3_Handler.Init.ClockPrescaler=ADC_CLOCK_SYNC_PCLK_DIV2; //同步时钟 不能打开ADC2的校准
ADC3_Handler.Init.Resolution=ADC_RESOLUTION_16B; //16位模式
ADC3_Handler.Init.ScanConvMode=ENABLE; //扫描模式
ADC3_Handler.Init.EOCSelection=ADC_EOC_SINGLE_CONV; //EOC全部转换完成进入中断
ADC3_Handler.Init.LowPowerAutoWait=DISABLE; //自动低功耗关闭
ADC3_Handler.Init.ContinuousConvMode=DISABLE; //关闭连续转换
ADC3_Handler.Init.NbrOfConversion=3; //3个转换在规则序列中
ADC3_Handler.Init.DiscontinuousConvMode=DISABLE; //禁止不连续采样模式
ADC3_Handler.Init.NbrOfDiscConversion=0; //不连续采样通道数为0
ADC3_Handler.Init.ExternalTrigConv=ADC_EXTERNALTRIG_T1_CC2; //定时器触发 TIME3-CH4
ADC3_Handler.Init.ExternalTrigConvEdge=ADC_EXTERNALTRIGCONVEDGE_RISING; //外部上升沿触发
ADC3_Handler.Init.BoostMode=ENABLE; //BOOT模式使能 时钟高于20MHz时 必须使能此位
ADC3_Handler.Init.Overrun=ADC_OVR_DATA_OVERWRITTEN; //有新的数据的后直接覆盖掉旧数据
ADC3_Handler.Init.OversamplingMode=DISABLE; //过采样关闭
ADC3_Handler.Init.ConversionDataManagement=ADC_CONVERSIONDATA_DMA_CIRCULAR; //DMA循环接受数据
HAL_ADC_Init(&ADC3_Handler); //初始化
//ADC3-Channel-2
ADC3_Channel_Handler.Channel=2; //通道 PF9
ADC3_Channel_Handler.Rank=ADC_REGULAR_RANK_1; //序列1
ADC3_Channel_Handler.SamplingTime=ADC_SAMPLETIME_2CYCLES_5; //采样周期
ADC3_Channel_Handler.SingleDiff=ADC_SINGLE_ENDED; //单边采集
ADC3_Channel_Handler.OffsetNumber=ADC_OFFSET_NONE;
ADC3_Channel_Handler.Offset=0;
HAL_ADC_ConfigChannel(&ADC3_Handler,&ADC3_Channel_Handler); //通道配置
//ADC3-Channel-7
ADC3_Channel_Handler.Channel=7; //通道 PF8
ADC3_Channel_Handler.Rank=ADC_REGULAR_RANK_2; //序列2
ADC3_Channel_Handler.SamplingTime=ADC_SAMPLETIME_2CYCLES_5; //采样周期
ADC3_Channel_Handler.SingleDiff=ADC_SINGLE_ENDED; //单边采集
ADC3_Channel_Handler.OffsetNumber=ADC_OFFSET_NONE;
ADC3_Channel_Handler.Offset=0;
HAL_ADC_ConfigChannel(&ADC3_Handler,&ADC3_Channel_Handler); //通道配置
//ADC3-Channel-3
ADC3_Channel_Handler.Channel=3; //通道 PF7
ADC3_Channel_Handler.Rank=ADC_REGULAR_RANK_3; //序列3
ADC3_Channel_Handler.SamplingTime=ADC_SAMPLETIME_2CYCLES_5; //采样周期
ADC3_Channel_Handler.SingleDiff=ADC_SINGLE_ENDED; //单边采集
ADC3_Channel_Handler.OffsetNumber=ADC_OFFSET_NONE;
ADC3_Channel_Handler.Offset=0;
HAL_ADC_ConfigChannel(&ADC3_Handler,&ADC3_Channel_Handler); //通道配置
HAL_ADCEx_Calibration_Start(&ADC3_Handler,ADC_CALIB_OFFSET,ADC_SINGLE_ENDED); //ADC校准
}
//ADC底层驱动 引脚配置、时钟使能
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
GPIO_InitTypeDef GPIO_Initure; //GPIO句柄
__HAL_RCC_ADC12_CLK_ENABLE(); //使能ADC1/2时钟
__HAL_RCC_ADC3_CLK_ENABLE(); //使能ADC1/2时钟
__HAL_RCC_GPIOA_CLK_ENABLE(); //开启GPIOA时钟
__HAL_RCC_GPIOF_CLK_ENABLE(); //开启GPIOC时钟
__HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_CLKP); //ADC外设时钟选择
GPIO_Initure.Pin=GPIO_PIN_0|GPIO_PIN_5|GPIO_PIN_6; //PA
GPIO_Initure.Mode=GPIO_MODE_ANALOG; //模拟
GPIO_Initure.Pull=GPIO_NOPULL; //不带上下拉
HAL_GPIO_Init(GPIOA,&GPIO_Initure);
GPIO_Initure.Pin=GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9; //PF
GPIO_Initure.Mode=GPIO_MODE_ANALOG; //模拟
GPIO_Initure.Pull=GPIO_NOPULL; //不带上下拉
HAL_GPIO_Init(GPIOF,&GPIO_Initure);
}
void ADC_Init(void)
{
ADC1_Init();
ADC3_Init();
}
DMA:
DMA_HandleTypeDef DMA1_Stream0_Handler; //DMA句柄
DMA_HandleTypeDef DMA1_Stream1_Handler; //DMA句柄
void DMA1_Stream0_Init(void)
{
__HAL_RCC_DMA1_CLK_ENABLE(); //DMA1时钟使能
//DMA1-Stream0
DMA1_Stream0_Handler.Instance=DMA1_Stream0; //数据流选择
DMA1_Stream0_Handler.Init.Request=DMA_REQUEST_ADC1; //ADC
DMA1_Stream0_Handler.Init.Direction=DMA_PERIPH_TO_MEMORY; //外设到储存器
DMA1_Stream0_Handler.Init.PeriphInc=DMA_PINC_DISABLE; //外设非增量模式
DMA1_Stream0_Handler.Init.MemInc=DMA_MINC_ENABLE; //存储器增量模式
DMA1_Stream0_Handler.Init.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD; //外设数据长度:16位
DMA1_Stream0_Handler.Init.MemDataAlignment=DMA_PDATAALIGN_HALFWORD; //存储器数据长度:16位
DMA1_Stream0_Handler.Init.Mode=DMA_CIRCULAR; //循环接受模式
DMA1_Stream0_Handler.Init.Priority=DMA_PRIORITY_HIGH; //高等优先级
DMA1_Stream0_Handler.Init.FIFOMode=DMA_FIFOMODE_DISABLE;
DMA1_Stream0_Handler.Init.FIFOThreshold=DMA_FIFO_THRESHOLD_FULL;
DMA1_Stream0_Handler.Init.MemBurst=DMA_MBURST_SINGLE; //存储器突发单次传输
DMA1_Stream0_Handler.Init.PeriphBurst=DMA_PBURST_SINGLE; //外设突发单次传输
//初始化
HAL_DMA_DeInit(&DMA1_Stream0_Handler);
HAL_DMA_Init(&DMA1_Stream0_Handler);
__HAL_LINKDMA(&ADC1_Handler,DMA_Handle,DMA1_Stream0_Handler); //将DMA与ADC1联系起来(发送DMA)
//开启中断 设置优先级
HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);
}
void DMA1_Stream1_Init(void)
{
__HAL_RCC_DMA1_CLK_ENABLE(); //DMA1时钟使能
//DMA1-Stream1
DMA1_Stream1_Handler.Instance=DMA1_Stream1; //数据流选择
DMA1_Stream1_Handler.Init.Request=DMA_REQUEST_ADC3; //ADC
DMA1_Stream1_Handler.Init.Direction=DMA_PERIPH_TO_MEMORY; //外设到储存器
DMA1_Stream1_Handler.Init.PeriphInc=DMA_PINC_DISABLE; //外设非增量模式
DMA1_Stream1_Handler.Init.MemInc=DMA_MINC_ENABLE; //存储器增量模式
DMA1_Stream1_Handler.Init.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD; //外设数据长度:16位
DMA1_Stream1_Handler.Init.MemDataAlignment=DMA_PDATAALIGN_HALFWORD; //存储器数据长度:16位
DMA1_Stream1_Handler.Init.Mode=DMA_CIRCULAR; //循环接受模式
DMA1_Stream1_Handler.Init.Priority=DMA_PRIORITY_HIGH; //高等优先级
DMA1_Stream1_Handler.Init.FIFOMode=DMA_FIFOMODE_DISABLE;
DMA1_Stream1_Handler.Init.FIFOThreshold=DMA_FIFO_THRESHOLD_FULL;
DMA1_Stream1_Handler.Init.MemBurst=DMA_MBURST_SINGLE; //存储器突发单次传输
DMA1_Stream1_Handler.Init.PeriphBurst=DMA_PBURST_SINGLE; //外设突发单次传输
//初始化
HAL_DMA_DeInit(&DMA1_Stream1_Handler);
HAL_DMA_Init(&DMA1_Stream1_Handler);
__HAL_LINKDMA(&ADC3_Handler,DMA_Handle,DMA1_Stream1_Handler); //将DMA与ADC1联系起来(发送DMA)
//开启中断 设置优先级
HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 0, 1);
HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);
}
void DMA_Init(void)
{
DMA1_Stream0_Init();
DMA1_Stream1_Init();
}
TIM_HandleTypeDef TIM1_Handler = {0}; //定时器句柄
TIM_OC_InitTypeDef sConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
//TIM1 PWM初始化
//arr:自动重装值
//psc:时钟预分频数
void TIM1_PWM_Init(u16 arr,u16 psc)
{
TIM1_Handler.Instance=TIM1; //定时器1
TIM1_Handler.Init.Prescaler=psc; //定时器分频
TIM1_Handler.Init.CounterMode=TIM_COUNTERMODE_UP; //向上计数模式
TIM1_Handler.Init.Period=arr; //自动重装载值
TIM1_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;
TIM1_Handler.Init.RepetitionCounter = 0;
TIM1_Handler.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
HAL_TIM_PWM_Init(&TIM1_Handler); //初始化PWM
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&TIM1_Handler, &sMasterConfig);
sConfig.OCMode=TIM_OCMODE_PWM1; //模式选择PWM1
sConfig.Pulse=arr/2; //设置比较值,此值用来确定占空比,默认比较值为自动重装载值的一半,即占空比为50%
sConfig.OCPolarity=TIM_OCPOLARITY_HIGH;
sConfig.OCNPolarity = TIM_OCPOLARITY_HIGH;
sConfig.OCFastMode = TIM_OCFAST_DISABLE;
sConfig.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfig.OCNIdleState = TIM_OCNIDLESTATE_RESET;
HAL_TIM_PWM_ConfigChannel(&TIM1_Handler,&sConfig,TIM_CHANNEL_1); //配置TIM1通道1
HAL_TIM_PWM_ConfigChannel(&TIM1_Handler,&sConfig,TIM_CHANNEL_2); //配置TIM1通道2
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
sBreakDeadTimeConfig.DeadTime = 0;
sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
sBreakDeadTimeConfig.BreakFilter = 0;
sBreakDeadTimeConfig.Break2State = TIM_BREAK2_DISABLE;
sBreakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_HIGH;
sBreakDeadTimeConfig.Break2Filter = 0;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
HAL_TIMEx_ConfigBreakDeadTime(&TIM1_Handler, &sBreakDeadTimeConfig);
HAL_TIM_PWM_Start(&TIM1_Handler,TIM_CHANNEL_1); //开启PWM通道1
HAL_TIM_PWM_Start(&TIM1_Handler,TIM_CHANNEL_2); //开启PWM通道2
}
//定时器底层驱动 时钟使能、引脚配置
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_TIM1_CLK_ENABLE(); //使能定时器1时钟
__HAL_RCC_GPIOE_CLK_ENABLE(); //开启GPIOE时钟
GPIO_Initure.Pin=GPIO_PIN_9 | GPIO_PIN_11; //PE9、PE11
GPIO_Initure.Mode=GPIO_MODE_AF_PP; //复用推完输出
GPIO_Initure.Pull = GPIO_NOPULL;
GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH; //高速
GPIO_Initure.Alternate=GPIO_AF1_TIM1; //复用为TIM1
HAL_GPIO_Init(GPIOE,&GPIO_Initure);
}
|
|