[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]
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
对于调试CCD,其实用法很简单,官方提供的代码一般就可以直接用。
还有就是串口是正常工作不,看看系统时钟是多少?
一周热门 更多>