基于STM32的CCD调试

2019-07-20 23:19发布

[mw_shl_code=c,true]各位大侠 新手报到第一次发帖求助多多关照[/mw_shl_code] [mw_shl_code=c,true]最近在做线性CCD 各种程序模块还有程序流程都是按照蓝宙的示例改的[/mw_shl_code] [mw_shl_code=c,true]但是使用蓝宙的上位机一直没有出现数据,都快搞死了,求助啊,[/mw_shl_code] [mw_shl_code=c,true] [mw_shl_code=c,true]////////////////////////////////////////////////////////////////////////////////// [/mw_shl_code] [mw_shl_code=c,true] [mw_shl_code=c,true]【main.c】[/mw_shl_code] [mw_shl_code=c,true] [mw_shl_code=c,true]int main(void) { u8 i=0; delay_init(); //延时函数初始化 LED_Init(); CCD_Init(); TIM3_Int_Init(9,7199); NVIC_Configuration(); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级 uart_init(9600); //串口初始化为9600 while(1) { if (Time50_Flag==1) { i++; if(i==20){ LED1=!LED1;i=0;} Calculate_Exposure_Time(); //每50ms计算一次曝光时间 CCD_Get(); //图像采集 Send_Data(); Time50_Flag=0; } } }[/mw_shl_code] 这里有一点特别奇怪,把LED的程序放在定时器中断里面 LED就不会发生变化
///////////////////////////////////////////////////////////////////////////////[/mw_shl_code] [mw_shl_code=c,true]【time.c】[/mw_shl_code] [mw_shl_code=c,true]//定时器3中断服务程序 void TIM3_IRQHandler(void)   //TIM3中断 {    //static u8 Exposure_Count=0,Exposure_Point;                      //计数//曝光点                              Exposure_Count++;    if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)  //检查TIM3更新中断发生与否 {      Exposure_Point =50 - Exposure_Time;                        // 根据曝光时间计算50ms周期内的曝光点         if (Exposure_Point >= 1)   { if (Exposure_Point == Exposure_Count)          //等待曝光点 {   CCD_Prepare();                               //曝光开始 }   }  if (Exposure_Count== 50) {       Time50_Flag=1;Exposure_Count = 0;      }   TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx更新中断标志    } } [/mw_shl_code] [mw_shl_code=c,true] [/mw_shl_code] [mw_shl_code=c,true]//////////////////////////////////////////////////////////////////////////////// [/mw_shl_code] 【 CCD.c 】 //CCD IO初始化 void CCD_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; ADC_InitTypeDef ADC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOx|RCC_APB2Periph_ADC1,ENABLE ); //使能ADC1通道时钟 RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M GPIO_InitStructure.GPIO_Pin = GPIO_Pin_CLK|GPIO_Pin_SI; //端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz GPIO_Init(GPIOX, &GPIO_InitStructure); //根据设定参数初始化 //PA1 作为模拟通道输入引脚 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_AO; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入引脚 GPIO_Init(GPIOX, &GPIO_InitStructure); ADC_DeInit(ADC1); //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值 ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作模式:ADC1和ADC2工作在独立模式 ADC_InitStructure.ADC_ScanConvMode = DISABLE; //模数转换工作在单通道模式 ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //模数转换工作在单次转换模式 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐 ADC_InitStructure.ADC_NbrOfChannel = 1; //顺序进行规则转换的ADC通道的数目 ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器 ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1 ADC_ResetCalibration(ADC1); //使能复位校准 while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束 ADC_StartCalibration(ADC1); //开启AD校准 while(ADC_GetCalibrationStatus(ADC1)); //等待校准结束 // ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能 } //获得ADC值 //ch:通道值 0~3 u16 Get_Adc(void) { //设置指定ADC的规则组通道,一个序列,采样时间 ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5 ); //ADC1,ADC通道,采样时间为239.5周期 ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能 while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束 return ADC_GetConversionValue(ADC1); //返回最近一次ADC1规则组的转换结果 } //第一个周期不采集,相当于准备工作, void CCD_Prepare(void) { u16 n; SI=1; delay_us(2); // CLK=1; delay_us(2); //ccd的每个AO采集时间不可低于0.125us,这里SI,CLK周期统一使用2us SI=0; delay_us(2); CLK=0; for(n=0;n<127;n++) { delay_us(2); CLK=1; delay_us(2); CLK=0; } delay_us(2); CLK=1; delay_us(2); CLK=0; } u16 CCD_Pixel[128]={0}; //CCD巡线函数:控制CCD工作并返回检测到的黑线中心像素坐标 void CCD_Get(void) { u16 i; SI=1; delay_us(2); CLK=1; delay_us(2); //ccd的每个AO采集时间不可低于0.125us,这里SI,CLK周期统一使用2us SI=0; delay_us(2); // for(i=0;i<10;i++) //稍做延时,等待采取第一个数据 决定图形平滑程度 // { //其实没多大作用 // delay_us(2); // } CCD_Pixel[0]=Get_Adc(); CCD_Pixel[0]=CCD_Pixel[0]/16; CLK=0; for(i=1;i<128;i++) { delay_us(2); CLK=1; delay_us(2); CCD_Pixel=Get_Adc(); CCD_Pixel[0]=CCD_Pixel[0]/16; CLK=0; } delay_us(2); CLK=1; delay_us(2); CLK=0; } //求像素的平均值 float CCD_Pixel_Average(void) { u8 i,sum; for(i=8;i<128;i++) //不要前八个点 { sum = sum + CCD_Pixel; } return ((float)sum/120); } /**************************************************************** * 函数名称:Calculate_Exposure_Time * 功能说明:计算曝光时间 ****************************************************************/ u8 Exposure_Time=10; void Calculate_Exposure_Time(void) { float Pixel_Average_Value; /* 128个像素点的平均AD值 */ float Pixel_Average_Voltage; /* 128个像素点的平均电压值*/ float Target_Pixel_Average_Voltage = 1.65; /* 设定目标平均电压值 */ float Delta_Pixel_Average_Voltage = 0; /* 设定目标平均电压值与实际值的偏差*/ float Allowed_Delta_Pixel_Average_Voltage =0.1; /* 设定目标平均电压值允许的偏差*/ Pixel_Average_Value =CCD_Pixel_Average(); /* 计算128个像素点的平均AD值 */ Pixel_Average_Voltage = Pixel_Average_Value *(3.3/256); /* 计算128个像素点的平均电压值 */ Delta_Pixel_Average_Voltage = Target_Pixel_Average_Voltage - Pixel_Average_Voltage; if(Delta_Pixel_Average_Voltage < -Allowed_Delta_Pixel_Average_Voltage) { Delta_Pixel_Average_Voltage = -Delta_Pixel_Average_Voltage; Exposure_Time = (unsigned char)(Exposure_Time - Delta_Pixel_Average_Voltage); } if(Delta_Pixel_Average_Voltage>Allowed_Delta_Pixel_Average_Voltage) { Exposure_Time = (unsigned char)(Exposure_Time + Delta_Pixel_Average_Voltage); } if(Exposure_Time <= 1) Exposure_Time = 1; if(Exposure_Time >= 50) //将曝光时间限制在50ms内 Exposure_Time = 50; }[/mw_shl_code]

[/mw_shl_code] [mw_shl_code=c,true]/************************************************** 函数名称 :Send_Data 功能说明:将数据发送到上位机 ***************************************************/ void Send_Data(void) { unsigned char i,temp; unsigned char crc = 0; USART_SendData(USART1,'*'); USART_SendData(USART1,'L'); USART_SendData(USART1,'D'); SendHex(0); SendHex(132); SendHex(0); SendHex(0); SendHex(0); SendHex(0); for(i=0; i<128; i++) // { temp=CCD_Pixel; SendHex(temp); // USART_SendData(USART1,CCD_Pixel); } SendHex(crc); USART_SendData(USART1,'#'); } /*************************************************** 函数名称:SendHex 功能说明:上位机接口程序 ***************************************************/ void SendHex(unsigned char hex) { unsigned char temp; temp = hex>>4; if(temp < 10) { USART_SendData(USART1,temp + '0'); } else { USART_SendData(USART1,temp - 10 + 'A'); } temp = hex & 0x0F; if(temp < 10) { USART_SendData(USART1,temp + '0'); } else { USART_SendData(USART1,temp - 10 + 'A'); } }[/mw_shl_code]
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
7条回答
莫恋&她
1楼-- · 2019-07-21 04:26
额 4年后才再次登录,问题已经解决。记得当时好像是因为存数据的最好用指针的类型,用数组就回出错,具体什么原理一直没搞懂。
对于调试CCD,其实用法很简单,官方提供的代码一般就可以直接用。
yediezeus
2楼-- · 2019-07-21 06:46
把LED放在定时器中断中,不发生变化,还是变化的太快你看不出来,如果进入调试模式,LED应该发生变化。
还有就是串口是正常工作不,看看系统时钟是多少?
莫恋&她
3楼-- · 2019-07-21 10:54
 精彩回答 2  元偷偷看……
我love寻水的鱼
4楼-- · 2019-07-21 15:30
楼主问题解决了吗??
我love寻水的鱼
5楼-- · 2019-07-21 16:18
 精彩回答 2  元偷偷看……
AV8D
6楼-- · 2019-07-21 22:01
你好。我也在研究TCD1209线阵CCD,你的驱动时序调试好了吗

一周热门 更多>