OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 2741|回复: 5

用tim4触发不了AD采样,DMA传输,啥情况?搜了下,发现好多兄弟都没成功

[复制链接]

8

主题

29

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
236
金钱
236
注册时间
2015-1-22
在线时间
72 小时
发表于 2020-8-27 09:43:34 | 显示全部楼层 |阅读模式
1金钱
void TIM4_Int_Init(u16 arr,u16 psc)
{
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        TIM_OCInitTypeDef TIM_OCInitStruct;
        
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
        TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值        
        TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
        TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
        TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位

        TIM_OCInitStruct.TIM_OCMode =TIM_OCMode_PWM1 ;
        TIM_OCInitStruct.TIM_OCPolarity =TIM_OCPolarity_High;
        TIM_OCInitStruct.TIM_OutputState =TIM_OutputState_Enable;
        TIM_OCInitStruct.TIM_Pulse =500;
        TIM_OC1Init(TIM4, &TIM_OCInitStruct);        
                                                
        TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable);         
        TIM_CtrlPWMOutputs(TIM4, ENABLE);
        TIM_Cmd(TIM4, ENABLE);  //使能TIMx        
        TST_GPIO_Init();
        //TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断
}
void DMA_ADC_INIT(void)
{
   DMA_InitTypeDef DMA_InitStructure;
   ADC_InitTypeDef ADC_InitStructure;

   RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);   
        
DMA_DeInit(DMA1_Channel1);                 //*DMA通道1*/
  DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;      /*外设地址*/
  DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&AD_Value[64][3]; /* 内存地址*/
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;               /* DMA 传输方向单向*/
  DMA_InitStructure.DMA_BufferSize =64*3;                          /* 设置DMA在传输时缓冲区的长度 word*/
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; /*设置DMA的外设递增模式,一个外设*/
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;         /*设置DMA的内存递增模式*/
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;  /*外设数据字长*/
  DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord;          /*内存数据字长*/
  DMA_InitStructure.DMA_Mode=DMA_Mode_Circular;     /*设置DMA的传输模式:连续不断的循环模式*/
  DMA_InitStructure.DMA_Priority=DMA_Priority_High; /*设置DMA的优先级别*/
  DMA_InitStructure.DMA_M2M=DMA_M2M_Disable;        /*设置DMA的2个memory中的变量互相访问*/
  DMA_Init(DMA1_Channel1, &DMA_InitStructure);
  DMA_Cmd(DMA1_Channel1, ENABLE);

  NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;  
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
  
  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;  /*独立的转换模式*/
  ADC_InitStructure.ADC_ScanConvMode = ENABLE;                 /*ENABLE-ADC多通道扫描, DISABLE-ADC单通道扫描*/
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;   /* ENABLE--ADC连续转化模式 DISABLE--ADC单次转化模式*/
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T4_CC4;        /*ADC外部开关,关闭状态*/
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;   /*对齐方式,ADC为12位中,右对齐方式*/
  ADC_InitStructure.ADC_NbrOfChannel =3;         /*开启通道数,1个*/
  ADC_Init(ADC1, &ADC_InitStructure);
  
  ADC_RegularChannelConfig(ADC1, ADC_Channel_0,  1, ADC_SampleTime_13Cycles5);   
  ADC_RegularChannelConfig(ADC1, ADC_Channel_1,  2, ADC_SampleTime_13Cycles5);   
  ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 3, ADC_SampleTime_13Cycles5);   
  ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 4, ADC_SampleTime_13Cycles5);
  ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 5, ADC_SampleTime_13Cycles5);
  ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 6, ADC_SampleTime_13Cycles5);
  
  ADC_DMACmd(ADC1, ENABLE); /* Enable ADC1 DMA */
  ADC_ExternalTrigConvCmd(ADC1, ENABLE);
  ADC_Cmd(ADC1, ENABLE);
  
  ADC_ResetCalibration(ADC1);/*重新校准*/
  while(ADC_GetResetCalibrationStatus(ADC1));/*等待重新校准完成*/
  ADC_StartCalibration(ADC1);/*开始校准*/
  while(ADC_GetCalibrationStatus(ADC1)); /*等待校准完成*/
//  ADC_SoftwareStartConvCmd(ADC1, ENABLE);/* Start ADC1 Software Conversion */
}

void DMA1_Channel1_IRQHandler(void)
{
        static u8 flg=0;        
        if(DMA_GetITStatus(DMA1_IT_TC1)!=RESET)
        {
                DMA_ClearITPendingBit(DMA1_IT_TC1);
                if(flg==0)
                {
                        GPIO_SetBits(GPIOA, GPIO_Pin_7);
                        flg=1;
                }
                else
                {
                        GPIO_ResetBits(GPIOA, GPIO_Pin_7);
                        flg=0;
                }        
               
        }
}

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165536
金钱
165536
注册时间
2010-12-1
在线时间
2117 小时
发表于 2020-8-28 02:08:20 | 显示全部楼层
回复

使用道具 举报

20

主题

450

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4910
金钱
4910
注册时间
2017-7-6
在线时间
720 小时
发表于 2020-8-28 09:38:50 | 显示全部楼层
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&AD_Value[64][3]; /* 内存地址*/
这里的语句来源地址赋值不是这样的,它是针对整个数组,不是某个字节,改成这样试试
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&AD_Value;
我是小白,很白很白的小白!!!
回复

使用道具 举报

20

主题

450

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4910
金钱
4910
注册时间
2017-7-6
在线时间
720 小时
发表于 2020-8-28 09:48:00 | 显示全部楼层
ADC_InitStructure.ADC_NbrOfChannel =3; 这个通道个数你也设置的不对啊
我看你下面是6个通道   
还有AD过来到哪个数组AD_Value你也设置的不对,你的AD采集顺序是AD0、AD1、AD10、AD11、AD12、AD13   那么你的二维数组顺序是这样走的,AD0对应AD_Value[0][1]、AD1对应AD_Value[0][2]、AD10对应AD_Value[0][3]、AD11对应AD_Value[0][4]、AD12对应AD_Value[0][4]、AD13对应AD_Value[0][5]、然后又到AD1开始了,AD1再对应AD_Value[1][0]..............AD13对应AD_Value[1][5],如果你是求AD采集10次平均值,数组就这样定义AD_Value[10][6]
我是小白,很白很白的小白!!!
回复

使用道具 举报

8

主题

29

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
236
金钱
236
注册时间
2015-1-22
在线时间
72 小时
 楼主| 发表于 2020-8-28 15:14:54 | 显示全部楼层
是,哪里确实错了。已经改好。
今天试了下定时器触发,两路AD同时采样,DMA不中断,大家看看哪里问题?
/这里使用的是定时器4!
void TIM4_Int_Init(u16 arr,u16 psc)
{
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        TIM_OCInitTypeDef TIM_OCInitStruct;
       
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
        TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值       
        TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
        TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
        TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位

        TIM_OCInitStruct.TIM_OCMode =TIM_OCMode_PWM1 ;
        TIM_OCInitStruct.TIM_OCPolarity =TIM_OCPolarity_Low;
        TIM_OCInitStruct.TIM_OutputState =TIM_OutputState_Enable;
        TIM_OCInitStruct.TIM_Pulse =324/2;
        TIM_OC4Init(TIM4, &TIM_OCInitStruct);                                               
        TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable);//TIMx_CCR1寄存器的预装载功能,Enable就是下一次更新事件时被更新;Disable是立即生效!!!         
        TIM_Cmd(TIM4, ENABLE);  //使能TIMx       
        TST_GPIO_Init();
//TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断
}


void GPIO_Ad_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 |GPIO_Pin_1 |GPIO_Pin_4 | GPIO_Pin_5;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  GPIO_Init(GPIOC, &GPIO_InitStructure);
}

void DMA_ADC_INIT(void)
{
        DMA_InitTypeDef DMA_InitStructure;
        ADC_InitTypeDef ADC_InitStructure;

        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);   
       
        DMA_DeInit(DMA1_Channel1);                 //*DMA通道1*/
  DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;      /*外设地址*/
  DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&AD_Value[0][0]; /* 内存地址*/
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;               /* DMA 传输方向单向*/
  DMA_InitStructure.DMA_BufferSize =32*2;                          /* 设置DMA在传输时缓冲区的长度 word*/
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; /*设置DMA的外设递增模式,一个外设*/
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;         /*设置DMA的内存递增模式*/
//  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;  /*外设数据字长*/
//  DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord;          /*内存数据字长*/
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;      //外设数据单位(每次传输32位)
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;              //内存数据单位(每次传输32位)
  DMA_InitStructure.DMA_Mode=DMA_Mode_Circular;     /*设置DMA的传输模式:连续不断的循环模式*/
  DMA_InitStructure.DMA_Priority=DMA_Priority_High; /*设置DMA的优先级别*/
  DMA_InitStructure.DMA_M2M=DMA_M2M_Disable;        /*设置DMA的2个memory中的变量互相访问*/
  DMA_Init(DMA1_Channel1, &DMA_InitStructure);
        DMA_ITConfig(DMA1_Channel1,DMA_IT_TC,ENABLE); //
        DMA_Cmd(DMA1_Channel1, ENABLE);

  
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE);
  ADC_DeInit(ADC1);
  ADC_DeInit(ADC2);
  
  ADC_StructInit(&ADC_InitStructure);
  ADC_InitStructure.ADC_Mode =  ADC_Mode_RegSimult;  //ADC1工作在注入模式
  ADC_InitStructure.ADC_ScanConvMode = ENABLE;                 /*ENABLE-ADC多通道扫描, DISABLE-ADC单通道扫描*/
  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;   /* ENABLE--ADC连续转化模式 DISABLE--ADC单次转化模式*/
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T4_CC4;//ADC_ExternalTrigConv_T4_CC4;ADC_ExternalTrigConv_None        /*ADC外部开关,关闭状态*/
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;   /*对齐方式,ADC为12位中,右对齐方式*/
  ADC_InitStructure.ADC_NbrOfChannel =2;         /*开启通道数,1个*/
  ADC_Init(ADC1, &ADC_InitStructure);
  ADC_DMACmd(ADC1, ENABLE); //使能ADC1的DMA
  
  ADC_StructInit(&ADC_InitStructure);
  ADC_InitStructure.ADC_Mode = ADC_Mode_RegSimult;  //ADC2工作在注入模式
  ADC_InitStructure.ADC_ScanConvMode = ENABLE;       /*ENABLE-ADC多通道扫描, DISABLE-ADC单通道扫描*/     
  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;   /* ENABLE--ADC连续转化模式 DISABLE--ADC单次转化模式*/
  ADC_InitStructure.ADC_ExternalTrigConv =  ADC_ExternalTrigConv_None;  //ADC_ExternalTrigConv_T4_CC4;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;   /*对齐方式,ADC为12位中,右对齐方式*/
  ADC_InitStructure.ADC_NbrOfChannel = 2;                //要进行ADC转换的通道数:PHASE_B_ADC_CHANNEL,TEMP_FDBK_CHANNEL
  ADC_Init(ADC2, &ADC_InitStructure);
  ADC_ExternalTrigConvCmd(ADC2, ENABLE);                 //ADC2外部触发使能,双ADC模式的从ADC必须要用这条语句
  
  
  ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_13Cycles5);   //A相电流
  ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_13Cycles5);   //母线电压
  ADC_RegularChannelConfig(ADC2, ADC_Channel_14, 1, ADC_SampleTime_13Cycles5);   //B相电流
  ADC_RegularChannelConfig(ADC2, ADC_Channel_15, 2, ADC_SampleTime_13Cycles5);   //温度电压

  ADC_Cmd(ADC1, ENABLE);                                   //ADC1使能     
  ADC_ResetCalibration(ADC1);                        //复位校准寄存器
  while(ADC_GetResetCalibrationStatus(ADC1));       //等待校准寄存器复位完成
  ADC_StartCalibration(ADC1);                        //ADC1开始校准
  while(ADC_GetCalibrationStatus(ADC1));            //等待校准完成

  ADC_Cmd(ADC2, ENABLE);                             //ADC2使能
  ADC_ResetCalibration(ADC2);                        //复位校准寄存器
  while(ADC_GetResetCalibrationStatus(ADC2));       //等待校准寄存器复位完成
  ADC_StartCalibration(ADC2);                        //ADC2开始校准  
  while(ADC_GetCalibrationStatus(ADC2));                   //等待校准完成
}
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165536
金钱
165536
注册时间
2010-12-1
在线时间
2117 小时
发表于 2020-8-29 01:58:53 | 显示全部楼层
帮顶
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-9 19:22

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表