全功能智能车之CCD ADC 触发DMA传输(第十四篇)
这篇主要讲CCD ADC 触发DMA传输,这算是完善一点原本的CCD等待ADC传输完成的功能,更加的提高了效率,这个最大的意义不在于此,而是在于以后的用定时器触发ADC,到那时就能够实现 定时器->ADC->DMA最后就只要去处理DMA完成的那个数据就行具体代码如下:
首先是主函数:
int main(void){ u16 i,cnt;Stm32_Clock_Init(9); //系统时钟设置 uart_init(72,115200); //串口初始化为115200 delay_init(72); //延时初始化 LED_Init(); //初始化与LED连接的硬件接口 LCD_Init(); //初始化LCD usmart_dev.init(72); //初始化USMART // TIM3_Int_Init(exposureTime-1,71); //初始化定时器用来采样CCD MYDMA_Config(DMA1_Channel1,(u32)Pixel);//初始化DMA1通道 CCD_init(); //初始化CCD //初始化数据for(i=0; i<CCD_LENGTH; i++) { Pixel=0;} POINT_COLOR=RED;//设置字体为红色 LCD_ShowString(60,10,200,16,16,"CCD TEST"); LCD_ShowString(60,30,200,16,16,"Maid:piaoran"); LCD_ShowString(60,50,200,16,16,"Date:2015-11-28"); LCD_ShowString(20,70,200,16,16,"ccd_max:0000ccd_min:0000"); LCD_ShowString(20,90,200,16,16,"exp_tim:0000ccd_avg:0000"); //VerifyExposure(); while(1) { ImageCapture(Pixel); if(++cnt >= 5) { cnt = 0; SendImageData(Pixel); } //LCD_Put32REG(0,130,"DMA->CNDTR:",DMA1_Channel1->CNDTR); LED0=!LED0; delay_ms(500); }}
这里调用了DMA初始化函数:
//DMA1的各通道配置//这里的传输形式是固定的,这点要根据不同的情况来修改//从存储器->外设模式/8位数据宽度/存储器增量模式//DMA_CHx:DMA通道CHx DMA_CHx即DMA通道,跟由什么触发DMA采样有关//cpar:外设地址//cmar:存储器地址 //外部中断触发定时器,定时器发出请求使DMA进行数据传输//cndtr:数据传输量 //用一个外部中断触发,触发DMA进行数据传输void MYDMA_Config(DMA_Channel_TypeDef* DMA_CHx,u32 cmar){ DMA_InitTypeDef DMA_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能DMA传输DMA_DeInit(DMA_CHx); //将DMA的通道1寄存器重设为缺省值 DMA_InitStructure.DMA_PeripheralBaseAddr =(u32)&ADC1->DR;//DMA外设数据寄存器的基地址 从ADC里获得数据 DMA_InitStructure.DMA_MemoryBaseAddr = cmar;//DMA内存基地址 数组的基地址 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//数据传输方向,从外设读取到DMA DMA_InitStructure.DMA_BufferSize = CCD_LENGTH ;//DMA通道的DMA缓存的大小,可以理解为DMA传输次数 // 最大传输数量为2^16-1=65535总共需要153600个字节。貌似超过了 所以一次采320*2 一行 ,采240次 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址寄存器不变 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//内存地址寄存器递增 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//外设数据宽度为8位即一个字节 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //DMA数据宽度为8位 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//工作在正常缓存模式 工作在单次模式,即只传输完一个流程 DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; //DMA通道 x拥有中优先级 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//DMA通道x没有设置为内存到内存传输 DMA_Init(DMA_CHx, &DMA_InitStructure);//根据DMA_InitStruct中指定的参数初始化DMA的通道USART1_Tx_DMA_Channel所标识的寄存器 NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;//DMA通道1中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//先占优先级0级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//从优先级3级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能 NVIC_Init(&NVIC_InitStructure);//根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器 DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);}
这里只是初始化,而使能在CCD采集函数中:/**************************************************************************函数名称:ImageCapture*功能说明:CCD采样程序*参数说明:* ImageData 采样数组*函数返回:无*修改时间:2015-11-28×作者: 蓝宙电子工作室 ×修改:piaoranQQ:384710930*备 注:ImageCapture(Pixel);*************************************************************************/void ImageCapture(unsigned short * ImageData) { unsigned char i; MYDMA_Enable(DMA1_Channel1);//使能TM3 TX DMA1 所指示的通道 DMA1->IFCR =0XFFFFFFFF; CCD_SI=1; SamplingDelay(); CCD_CLK=1; SamplingDelay(); CCD_SI=0; SamplingDelay(); Adc_auto(); CCD_CLK=0; for(i=0; i<127; i++) { SamplingDelay(); CCD_CLK=1; SamplingDelay(); Adc_auto(); CCD_CLK=0; } SamplingDelay(); CCD_CLK=1; SamplingDelay(); CCD_CLK=0; }
其中的使能函数如下,注意这里要在失能的情况下才能够在赋值字节数:
//开启一次DMA传输void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx){ DMA_Cmd(DMA_CHx, DISABLE );//关闭DMA_CHx DMA1 所指示的通道 DMA_SetCurrDataCounter(DMA_CHx,CCD_LENGTH);//DMA通道的DMA缓存的大小 DMA_Cmd(DMA_CHx, ENABLE);//使能DMA通道}
那DMA传输完成128个半字后将进入DMA传输完成中断,代码如下://DMA传输完成中断函数void DMA1_Channel1_IRQHandler(void){ DMA_ClearITPendingBit(DMA1_IT_GL1); LED1=!LED1; MYDMA_Enable(DMA1_Channel1);}还有一个代码片段就是ADC的初始化函数,这里使能了ADC的DMA功能:
//初始化ADC//这里我们仅以规则通道为例//我们默认仅开启通道1 voidAdc_Init(void){ //先初始化IO口 RCC->APB2ENR|=1<<2; //使能PORTA口时钟 GPIOA->CRL&=0XFFFFFF0F;//PA1 anolog输入 //通道10/11设置 RCC->APB2ENR|=1<<9; //ADC1时钟使能 RCC->APB2RSTR|=1<<9; //ADC1复位 RCC->APB2RSTR&=~(1<<9);//复位结束 RCC->CFGR&=~(3<<14); //分频因子清零 //SYSCLK/DIV2=12M ADC时钟设置为12M,ADC最大时钟不能超过14M! //否则将导致ADC准确度下降! RCC->CFGR|=2<<14; ADC1->CR1&=0XF0FFFF; //工作模式清零 ADC1->CR1|=0<<16; //独立工作模式 ADC1->CR1&=~(1<<8); //非扫描模式 ADC1->CR2&=~(1<<1); //单次转换模式 ADC1->CR2&=~(7<<17); ADC1->CR2|=7<<17; //软件控制转换 ADC1->CR2|=1<<20; //使用用外部触发(SWSTART)!!! 必须使用一个事件来触发 ADC1->CR2&=~(1<<11); //右对齐 //设置转换序列 设置CCD的通道 ADC1->SQR3&=0XFFFFFFE0; //规则序列1 通道ch ADC1->SQR3|=CCD_Channel; //设置CCD的通道 //设置通道1的采样时间 ADC1->SMPR2&=~(7<<3);//通道1采样时间清空 ADC1->SMPR2|=7<<3; //通道1239.5周期,提高采样时间可以提高精确度 ADC1->CR2|=1<<8; //使能ADC的DMA ADC1->CR2|=1<<0; //开启AD转换器 ADC1->CR2|=1<<3; //使能复位校准 while(ADC1->CR2&1<<3); //等待校准结束 //该位由软件设置并由硬件清除。在校准寄存器被初始化后该位将被清除。 ADC1->CR2|=1<<2; //开启AD校准 while(ADC1->CR2&1<<2);//等待校准结束 //该位由软件设置以开始校准,并在校准结束时由硬件清除}
还有就是触发ADC的函数,代码如下:
void Adc_auto(void) { ADC1->CR2|=1<<22; //启动规则转换通道 }
至此CCD的ADC触发DMA的功能就此完成,下一步要做的将是定时器触发ADC传输,这样之后CCD采集函数将全部由中断函数来完成。
现在来看看实验效果:
http://img.blog.csdn.net/20151129202350164?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Centerhttp://img.blog.csdn.net/20151129202412053?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Centerhttp://img.blog.csdn.net/20151129202419689?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Centerhttp://img.blog.csdn.net/20151129202433438?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Centerhttp://img.blog.csdn.net/20151129202445853?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Centerhttp://img.blog.csdn.net/20151129202511232?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
源代码下载地址:
http://download.csdn.net/detail/chengdong1314/9310431
页:
[1]