DMA 传输一半中断
初始化我这样配置DMA_ITConfig(DMA1_Channel1, DMA_IT_HT, ENABLE);
DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, DISABLE);
DMA_ClearITPendingBit(DMA_IT_HT);
DMA_ClearITPendingBit(DMA_IT_TC);
中断我这样做
u8 Test_Flag=0;
void DMA1_Channel1_IRQHandler(void)
{
if(DMA_GetITStatus(DMA_IT_TC)==SET)
{
DMA_ClearITPendingBit(DMA_IT_TC);
if(Test_Flag)
{
Test_Flag=0;
SDA_H;
}
else
{
Test_Flag=1;
SDA_L;
}
}
}
结果就是它执行了中断里面的TC中断程序。问题:为什么关了TC中断,只开HT中断,也会产生TC中断?
然后我经过测试,发现 HT的TC的中断执行时间是一样的,得出一个结果HT中断和TC中断是一样的。问题:传输一半中断是不是不能实现?
我测试1us下,HT和TC产生的中断和下次产生的间隔相差为500us,我用的是1000组采集。定时器为10us。如下:
ADC_ConvHalfCp:9029,496
ConvCplt:9029,0
ADC_ConvHalfCp:9079,496
ConvCplt:9079,0
ADC_ConvHalfCp:9130,496
ConvCplt:9130,0
TC情况下测试的是1000us,定时器为10us,如下:
ConvCplt:190,0
ConvCplt:290,0
ConvCplt:391,0
ConvCplt:492,0
ConvCplt:593,0
ConvCplt:694,0
ConvCplt:794,0 我用的是103测试的。楼主可以看一下。
不清楚你的DMA测试是测试的单次还是连续测试的,但是我觉得你得多看下手册,TC标识是由硬件触发的,因此不管你有没有使能TC中断,只要发送完成,TC标识就会置位,只是它不触发中断,如果你DMA只测试了一次应该是不会执行你中断里面的条件语句,如果是多次DMA测试我想的确是会进的吧,不晓得分析的对不对。 安 发表于 2016-11-10 15:38
我用的是103测试的。楼主可以看一下。
我明白了,我们的程序没问题。 是我误会了其中的意思了,半传输中断,只在DMA传输到一半时才产生。第一次中断是在传输了BUFF/2之时,第二次中断也是在传输了BUFF/2之时。两次中断间隔之间,其实传输了整个BUFF。 也就是说每中断一次需要的时间是传输整个BUFF的时间。也就是说TC中断时间=HT中断时间。 根据楼主的情况,结合以往,绝大多数的问题都是提出问题的楼主自行解决的,因为所有发言的人都是在你提供的非常有限的信息里凭经验猜。这个猜,或许能给你一些启发,最终解决问题的还是你自己。 楼主可以测试一下,当中断产生时,看一下DMA的中断寄存器的值。 anobodykey 发表于 2016-11-7 11:34
不清楚你的DMA测试是测试的单次还是连续测试的,但是我觉得你得多看下手册,TC标识是由硬件触发的,因此不管 ...
手册里面是这么说的 the TC flag is set and an interrupt is generated if the TCIE bit is set。到底是你熟悉还是我不熟悉,你自己看看 二楼回复,楼主说的很有火药味啊,大家都不敢发言了。 高二毛 发表于 2016-11-7 13:59
二楼回复,楼主说的很有火药味啊,大家都不敢发言了。
火药味重了就不敢发言吗?总是唯唯诺诺,遇事害怕,怎么会有出息,有本事就把问题解决,我就服你 安 发表于 2016-11-7 14:09
楼主可以测试一下,当中断产生时,看一下DMA的中断寄存器的值。
看了,TC 和 HT中断标志一起产生,而且每次中断都是DMA全部传输完成中断,根本就不是传输一半中断。最后没办法在中断里面做了个动作,buff总共大小500,结果每次都跳进if里面 说明每次整个buff都被更新了
if((RegularConvData_Tab!=0xff)&&(RegularConvData_Tab!=0xff))
{
RegularConvData_Tab=0xff;
}
RegularConvData_Tab=0xff;
RegularConvData_Tab=0xff; 楼主用的哪个CPU。 安 发表于 2016-11-7 15:58
楼主用的哪个CPU。
STM32F072C8 安 发表于 2016-11-7 15:58
楼主用的哪个CPU。
void ADC_Config(MEA_RANGE_TypeDef MeaRange)
{
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
Clear_Buff((u8*)RegularConvData_Tab,DMA_BUFF_SIZE*2);
RegularConvData_Tab=0xff;
RegularConvData_Tab=0xff;
/* ADC1 DeInit */
ADC_DeInit(ADC1);
/* ADC1 Periph clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
//把要AD的口配置为模拟输入其它两个配置为高阻这里要测试输入超过4V怎么办
switch(MeaRange)
{
case RANG_70DB:
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_70DB ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIO_PORT_70DB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;//高阻态
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_100DB ;
GPIO_Init(GPIO_PORT_100DB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_130DB ;
GPIO_Init(GPIO_PORT_130DB, &GPIO_InitStructure);
break;
case RANG_100DB:
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_100DB ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIO_PORT_100DB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;//高阻态
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_70DB ;
GPIO_Init(GPIO_PORT_70DB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_130DB ;
GPIO_Init(GPIO_PORT_130DB, &GPIO_InitStructure);
break;
case RANG_130DB:
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_130DB ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIO_PORT_130DB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;//高阻态
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_100DB ;
GPIO_Init(GPIO_PORT_100DB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_70DB ;
GPIO_Init(GPIO_PORT_70DB, &GPIO_InitStructure);
break;
}
/* Initialize ADC structure */
ADC_StructInit(&ADC_InitStructure);
/* Configure the ADC1 in continuous mode withe a resolution equal to 12 bits*/
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Upward;
ADC_Init(ADC1, &ADC_InitStructure);
//把要AD的口配置为模拟输入其它两个配置为高阻这里要测试输入超过4V怎么办
switch(MeaRange)
{
case RANG_70DB:
/* Convert the ADC1 Channel11 and channel10 with 28 Cycles as sampling time */
ADC_ChannelConfig(ADC1, ADC_Channel_1 , ADC_SampleTime_13_5Cycles);
break;
case RANG_100DB:
/* Convert the ADC1 Channel11 and channel10 with 28 Cycles as sampling time */
ADC_ChannelConfig(ADC1, ADC_Channel_2 , ADC_SampleTime_13_5Cycles);
break;
case RANG_130DB:
/* Convert the ADC1 Channel11 and channel10 with 28 Cycles as sampling time */
ADC_ChannelConfig(ADC1, ADC_Channel_3 , ADC_SampleTime_13_5Cycles);
break;
}
/* ADC Calibration */
ADC_GetCalibrationFactor(ADC1);
/* ADC DMA request in circular mode */
ADC_DMARequestModeConfig(ADC1, ADC_DMAMode_Circular);
/* Enable ADC_DMA */
ADC_DMACmd(ADC1, ENABLE);
/* Enable the ADC peripheral */
ADC_Cmd(ADC1, ENABLE);
/* Wait the ADRDY flag */
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADRDY));
/* ADC1 regular Software Start Conv */
ADC_StartOfConversion(ADC1);
}
void DMA_Config(void)
{
DMA_InitTypeDef DMA_InitStructure;
/* DMA1 clock enable */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 , ENABLE);
NVIC_DMA_Config();
/* DMA1 Channel1 Config */
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_Address;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)RegularConvData_Tab;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = DMA_BUFF_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_HT, ENABLE);
DMA_ClearITPendingBit(DMA_IT_HT);
/* DMA1 Channel1 enable */
DMA_Cmd(DMA1_Channel1, ENABLE);
}
void NVIC_DMA_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
u8 Test_Flag=0,Errno;
void DMA1_Channel1_IRQHandler(void)
{
ADC_StopOfConversion(ADC1);
DMA_Cmd(DMA1_Channel1, DISABLE);
if(DMA_GetITStatus(DMA_IT_HT)==SET)
{
if((RegularConvData_Tab!=0xff)&&(RegularConvData_Tab!=0xff))
{
Errno=1;
}
RegularConvData_Tab=0xff;
RegularConvData_Tab=0xff;
DMA_ClearITPendingBit(DMA1_IT_GL1);
if(Test_Flag)
{
Test_Flag=0;
SDA_H;
}
else
{
Test_Flag=1;
SDA_L;
}
}
DMA_Cmd(DMA1_Channel1, ENABLE);
ADC_StartOfConversion(ADC1);
}