中级会员
- 积分
- 331
- 威望
- 198
- 贡献
- 95
- 兑换币
- 58
- 注册时间
- 2012-3-28
- 在线时间
- 19 小时
- 毕业学校
- 山东轻工业学院
|
#include <hidef.h>
#include "derivative.h"
#include <MC9S12XS128.h>
#include "5X8ziku.h"
#define uchar unsigned char
#define uint unsigned int
//LCD_RST
#define LCD_RST_SET PORTB_PB1=1 //PC1
#define LCD_RST_RESET PORTB_PB1=0//PC1
//LCD_SCLK
#define LCD_SCLK_SET PORTB_PB4=1 //PC4
#define LCD_SCLK_RESET PORTB_PB4=0//PC4
//LCD_SDA
#define LCD_SDA_SET PORTB_PB3=1 //PA3
#define LCD_SDA_RESET PORTB_PB3=0//PA3
//LCD_RS
#define LCD_RS_SET PORTB_PB2=1 //PC2
#define LCD_RS_RESET PORTB_PB2=0//PC2
//LCD_CS
#define LCD_CS_SET PORTB_PB0=1 //PA0
#define LCD_CS_RESET PORTB_PB0=0//PA0
#define ROW 40
#define COLUMN 120
#define txd PORTA_PA0
uchar Image_Data[ROW][COLUMN];
static uchar sz[40]={ 30,31,32,
34,36,38,
41,44,47,
51,55,59,
64,69,74,
80,86,92,
98,104,110,
116,122,128,
134,140,146,
152,158,164,
170,176,182,
188,194,200,
206,212,218,
224//,230
};
static int turn;
static uchar Line_CL=0,Line_C=0,md,MP0,MP1,MP2;
static uint yw; //目标车速
static int wc1,wc2,PWM,yjwc,new,old;//误差 1 2 3
static uchar VSYN_C=0; //场数
/***************************************************
** 函数名称: PLL_Init
** 功能描述: 时钟初始化函数
** 说明: PLLCLK=2*OSCCLK(外部晶振时钟)*(SYNR+1)/(REFDV=+1)
****************************************************/
void PLL_Init(void) //(以下带括号的都是标注的查询信息)
{
CLKSEL=0x00; //(PLL系统脱离)
PLLCTL_PLLON=1; //(打开PLL)
SYNR=0XC0 | 0X08; // 08,01 72MHz 0B,01 96MHz (时钟合成寄存器)
REFDV=0X80 | 0X01; //(时钟分频寄存器)
POSTDIV=0X00;
_asm(nop); //(执行一个空语句 null opreation 延时有时软件抗干扰时要用到,使跑飞的程序入正轨)
_asm(nop);
while(0==CRGFLG_LOCK);//锁相环锁定 (是不是需改成这个while(!(CRGFLG_LOCK==1)); //when pll is steady ,then use it;)
CLKSEL_PLLSEL=1;//选定外部时钟 (PLL系统进行)
}
void Delay(uint cs)
{ uint csbl;
for(csbl=0;csbl<cs;csbl++)
_asm(nop);
}
/***************************************************
** 函数名称: TIM_Init
** 功能描述: 行场中断初始化函数
** 说明: ECT模块
****************************************************/
void TIM_Init(void)
{
TIOS=0x00; //外部输入捕捉 0,1 通道
TCTL4=0x09; //通道 0上升沿触发,通道 1 下降沿触发 (TCTL4=0x06; //通道0上升沿触发,通道 1 下降沿触发)
TSCR1=0x80; //使能
TIE=0x02; //通道 1中断使能 这里只开启场中断 后面场中断中开启行中断 (TIE=0x03;//通道 0,1 中断使能)
TFLG1=0xFF; //清中断标志位
}
/***************************************************
** 函数名称: SCI_Init
** 功能描述: 串口初始化函数
** 说明: 当PLLSET=1时BusClock=PLLCLK/2 当PLLSET=0时BusClock=OSCCLK/2
** 比特率:Baud Rate=BusClock/(16*SCIBD)
****************************************************/
void SCI_Init()
{
SCI0BD=0xEA; // Baud Rate=BusClock/(16*SCIBD)
//BusClock 72MHz, 19200bps,SCI0BD=0xEA
//BusClock 96MHz, 19200bps,SCI0BD=0x138
SCI0CR1=0x00; //正常8位模式,无奇偶校验
SCI0CR2=0x2C; //发送允许 接受中断允许
}
/**************************************************
** 函数名称: SCI_Write
** 功能描述: 给串行口写一个字符数据
** 输 入: SendChar为写入字符
** 输 出: 无
** 说明:
***************************************************/
void SCI_Write(uchar SendChar)
{
while (!(SCI0SR1&0x80));
SCI0DRH=0; //高位寄存器一般用不到
SCI0DRL=SendChar; //SCI0D RL相当于51中的SUBBF寄存器
}
/*---------------读取图像数值------------------*/
void Read_sz(uchar lie,uchar hang)
{
if(txd==1)
Image_Data[lie][hang]=0x00;
else
Image_Data[lie][hang]=0xff;
}
/**************************************************
** 函数名称: 减速控制
** 功能描述: 入弯减速
** 输 入:
** 输 出:
***************************************************/
void jian_su(uint i)
{
PWMPER23=0;
wc2=wc1-(i-yw);
//SCI_Write(yw);
PWM=PWM+ wc1*wc1*wc1+wc2*wc2*wc2;
if (PWM>1800)
PWM=1800;
else if (PWM < 0)
PWM=0;
PWMPER45=PWM;
wc1=i-yw;
}
//---------------------中断定义---------------------
#pragma CODE_SEG NON_BANKED
/**************************************************
** 函数名称: 中断处理函数
** 功能描述: 行中断处理函数
** 输 入: 无
** 输 出: 无
** 说明: 中断8
***************************************************/
interrupt 8 void HREF_Count(void)
{
uchar j;
TFLG1_C0F = 1; //清8中断
if(Line_CL == sz[Line_C])
{
Delay(30);
for(j=0;j<COLUMN; j++)
{
_asm(nop);//yanshi
Image_Data[Line_C][j]=PORTA;
}
Line_C++;
}
if( Line_C < 40)
Line_CL++; //行数加一
}
/**************************************************
** 函数名称: 中断处理函数
** 功能描述: 场中断处理函数
** 输 入: 无
** 输 出: 无
** 说明: 中断9
***************************************************/
interrupt 9 void VSYN_Interrupt(void)//优先级高
{
VSYN_C++; //场数加一
//PORTB=VSYN_C; //PORTB口输出当前场数
Line_CL = 0; //行中断次数清零
Line_C = 0;
TIE=0x03; //行场中断同时开启
TFLG1_C1F = 1; //清9中断
TFLG1_C0F = 1; //清8中断
yw=PACNT&0X0fff;
PACNT=0x0000;
}
/***********************************液晶lcd12864**********************************************/
void delay_us(uint time)
{
while (time--);
}
/* 毫秒级延时函数 */
void delay(uint time)
{
while(time--) delay_us(100);
}
void FSPI_SendData(uchar data1)
{
uchar i;
for(i=0;i<8;i++)
{
LCD_SCLK_RESET;
if(data1&0x80)
LCD_SDA_SET;
else
LCD_SDA_RESET;
LCD_SCLK_SET;
data1=data1<<=1;
}
}
/*******************************************************************************
//函数名: Lcdwritecom
//功能:lcd写指令
//输入:com指令
//输出:无
********************************************************************************/
void Lcdwritecom(uchar com)
{
LCD_CS_RESET; //片选拉低,选中LCD
LCD_RS_RESET; //设置为写命令
FSPI_SendData(com);
LCD_CS_SET; //片选拉高,释放LCD
}
/*******************************************************************************
//函数名:Lcdwritedata
//功能:lcd写数据
//输入:dat数据
//输出:无
********************************************************************************/
void Lcdwritedata(uchar dat)
{
LCD_CS_RESET; //片选拉低,选中LCD
LCD_RS_SET; //设置为写数据
FSPI_SendData(dat);
LCD_CS_SET; //片选拉高,释放LCD
}
/*LCD模块初始化*/
void initial_lcd()
{
LCD_CS_RESET;
LCD_RST_RESET; /*低电平复位*/
delay(20);
LCD_RST_SET ; /*复位完毕*/
delay(20);
Lcdwritecom(0xe2); /*软复位*/
delay(5);
Lcdwritecom(0x2c); /*升压步聚1*/
delay(5);
Lcdwritecom(0x2e); /*升压步聚2*/
delay(5);
Lcdwritecom(0x2f); /*升压步聚3*/
delay(5);
Lcdwritecom(0x24); /*粗调对比度,可设置范围0x20~0x27*/
Lcdwritecom(0x81); /*微调对比度*/
Lcdwritecom(0x20); /*0x28,微调对比度的值,可设置范围0x00~0x3f*/
Lcdwritecom(0xa2); /*1/9偏压比(bias)*/
Lcdwritecom(0xc8); /*行扫描顺序:从上到下*/
Lcdwritecom(0xa0); /*列扫描顺序:从左到右*/
Lcdwritecom(0x40); /*起始行:第一行开始*/
Lcdwritecom(0xaf); /*开显示*/
LCD_CS_SET;
}
void lcd_address(uint page,uint column)
{
column=column-0x01;
Lcdwritecom(0xb0+page-1); /*设置页地址*/ //1-8
Lcdwritecom(0x10+(column>>4&0x0f)); /*设置列地址的高4位*///0-128
Lcdwritecom(column&0x0f); /*设置列地址的低4位*/
}
/*全屏清屏*/
void clear_screen()
{
unsigned char i,j;
LCD_CS_RESET;
for(i=0;i<9;i++)
{
Lcdwritecom(0xb0+i);
Lcdwritecom(0x10);
Lcdwritecom(0x00);
for(j=0;j<132;j++)
{
Lcdwritedata(0x00);
}
}
LCD_CS_SET;
}
/*显示128x64点阵图像*/
void display_128x64(uchar *dp)
{
uint i,j;
LCD_CS_RESET;
for(j=0;j<8;j++)
{
lcd_address(j+1,1);
for (i=0;i<128;i++)
{
Lcdwritedata(*dp); /*写数据到LCD,每写完一个8位的数据后列地址自动加1*/
dp++;
}
}
LCD_CS_SET;
}
/*显示16x16点阵图像、汉字、生僻字或16x16点阵的其他图标*/
void display_graphic_16x16(uint page,uint column,uchar *dp)
{
uint i,j;
LCD_CS_RESET;
for(j=0;j<2;j++)
{
lcd_address(page+j,column);
for (i=0;i<16;i++)
{
Lcdwritedata(*dp); /*写数据到LCD,每写完一个8位的数据后列地址自动加1*/
dp++;
}
}
LCD_CS_SET;
}
/*显示8x16点阵图像、ASCII, 或8x16点阵的自造字符、其他图标*/
void display_graphic_8x16(uint page,uchar column,uchar *dp)
{
uint i,j;
LCD_CS_RESET;
for(j=0;j<2;j++)
{
lcd_address(page+j,column);
for (i=0;i<8;i++)
{
Lcdwritedata(*dp); /*写数据到LCD,每写完一个8位的数据后列地址自动加1*/
dp++;
}
}
LCD_CS_SET;
}
/*显示5*8点阵图像、ASCII, 或5x8点阵的自造字符、其他图标*/
void display_graphic_5x8(uint page,uchar column,uchar *dp)
{
uint col_cnt;
LCD_CS_RESET;
lcd_address(page,column);
for (col_cnt=0;col_cnt<5;col_cnt++)
{
Lcdwritedata(*dp);
dp++;
}
LCD_CS_SET;
}
void ASCII_function(uint page,uchar column,uchar zz)
{
uchar *dp;
dp=ziku5x8+zz*5-0xA0;
display_graphic_5x8(page,column,dp);
}
void lcd_xianshi(uint page,uchar column,uint i)
{
uint j,z;
uchar n=0,wz,m[20];
j=i;
while(j > 0)
{
z=j/10;
m[n]=j-z*10;
j=z;
n++;
}
wz=column;
for(;n>0;n--)
{
ASCII_function(page,wz,m[n-1]+0x30);
wz=wz+5;
}
ASCII_function(page,wz,0x20);
}
void String_function(uint page,uchar column,uchar *dp)
{
while(dp[0] != 0x20)
{
ASCII_function(page,(column-1)*5+1,dp[0]);
column++;
dp++;
}
}
void xstx()
{
uchar i,j,tx,u,m;
for(j=0;j<120;)
{
for(u=0;u<5;)
{
m=u*8+i;
switch (i)
{
case 0: tx=Image_Data[m][j]+tx;break;
case 1: tx=Image_Data[m][j]*2+tx;break;
case 2: tx=Image_Data[m][j]*4+tx;break;
case 3: tx=Image_Data[m][j]*8+tx;break;
case 4: tx=Image_Data[m][j]*16+tx;break;
case 5: tx=Image_Data[m][j]*32+tx;break;
case 6: tx=Image_Data[m][j]*64+tx;break;
case 7: tx=Image_Data[m][j]*128+tx;break;
}
i++;
if(i==8)
{
lcd_address(u+4,j+1);
Lcdwritedata(tx);
tx=0;
i=0;
u++;
}
}
j++;
}
}
/**************************************************
** 函数名称: zongxiang
** 功能描述: 纵向查找边界
** 输 入:位置 横向:hang 纵向:lie
** 输 出: 查找的位置
** 说明:
***************************************************/
uchar zongxiang(uchar hang,uchar lie) //纵向查找
{
while(Image_Data[hang][lie]==0x00)//白色查找 00为黑
{
hang--;
if(hang==0)
break;
}
return hang ; //列中线上黑白交界的行数
}
/**************************************************
** 函数名称: Left_find
** 功能描述: 查找左边界
** 输 入: 位置 横向:hang 纵向:lie
** 输 出: 查找的左边界
** 说明:
***************************************************/
uchar Left_find(uchar hang,uchar lie)
{
uchar i,j;
i=hang; j=lie;
while(Image_Data[j]==0x00)//白色查找
{
j--;
if(j==0)
break;
}
return j;//左边界
}
/**************************************************
** 函数名称: Right_find
** 功能描述: 查找右边界
** 输 入: 位置 横向:hang 纵向:lie
** 输 出: 查找的右边界
** 说明:
***************************************************/
uchar Right_find(uchar hang,uchar lie)
{
uchar i,j;
i=hang; j=lie;
while(Image_Data[j]==0x00)//白色查找
{
j++;
if(j==COLUMN)
break;
}
return j;//右边界
}
/**************************************************
** 函数名称: Middle_find
** 功能描述: 查找中间列上与行的交点
** 输 入: 位置 横向:hang 纵向: lie
** 输 出: 与中间列相交的行数
** 说明:
***************************************************/
uchar Middle_find(uchar hang ,uchar lie)
{
uchar zb,yb,md;
zb=Left_find(hang,lie);
yb=Right_find(hang,lie);
md=(zb+yb)/2;
//lcd_xianshi(1,1,md);
//PORTB=md;
return md;
}
void yunxing()
{
uchar md,zb,yb;//中线数值 左边 右边
MP1=zongxiang(40,60);//中间列数据
//lcd_xianshi(2,20,MP1);
if (MP1==0) //直道
{
md=Middle_find(20,60);
turn=(md-60)*10;
}
else if(MP1 < 18 )//微调入弯
{
MP0=zongxiang(40,30);
MP2=zongxiang(40,90);
if(MP0>MP2)
{
turn=MP1*25;
}
else if (MP0<MP2)
{
turn=-MP1*25;
}
}
else
{
new=MP1-18;
yjwc=new-old;
MP0=zongxiang(40,40);
MP2=zongxiang(40,80);
if(MP0>MP2)
{
turn=turn+new*10+yjwc*2;
}
else if (MP0<MP2)
{
turn=turn-(new*10+yjwc*2);
}
old=new;
}
if (turn>400)
turn=400;
else if(turn<-400)
turn=-400;
PWMDTY01 = 1500-turn;
}
/*************************************************************
舵机初始化
*************************************************************/
void PWM_01(void)
{
PWME_PWME1 = 0;
PWMCTL_CON01=1; //0和1联合成16位PWM;
PWMCAE_CAE1=0; //选择输出模式为左对齐输出模式
PWMCNT01 = 0; //计数器清零;
PWMPOL_PPOL1=1; //先输出高电平,计数到DTY时,反转电平
PWMPRCLK = 0X22; //clockA 不分频,clockB=busclock;clockA 4分频:18Mhz
PWMSCLA = 0x09; //对clockSA 18分频,clockSA=clockA/(2*PWMSCLA);
PWMCLK_PCLK1 = 1; //选择clockSA做时钟源 1Mhz 周期为1微秒
PWMPER01 = 20000; //0x57 PWM1的周期16ms 50Hz PWMx的周期=通道时钟周期*PWMPERx
PWMDTY01 = 1500; //0x6 当PWMPOL_PPOLx为高电平时 占空比=PWMDTYx/PWMPERx
PWME_PWME1 = 1;
}
/*************************************************************/
/* 电机初始化 */
/*************************************************************/
void PWM_35(void)
{
PWMCTL_CON23= 1; //通道23为16位的PWM
PWMCTL_CON45= 1; //通道01为16位的PWM
PWMPOL_PPOL5= 1; //通道的极性为高电平有效
PWMPOL_PPOL3= 1; //通道的极性为高电平有效
PWMPRCLK = 0x22; //总线时钟72mhz,A时钟和B时钟的分频系数为4,频率为18MHz
PWMSCLA = 9; //SA时钟频率为1MHz
PWMSCLB = 9;
PWMCLK_PCLK5= 0; //45和23用A,B时钟
PWMCLK_PCLK3= 0;
PWMCAE = 0x00; //脉冲模式为左对齐模式
PWMPER45 = 1800; //通道01的周期为10KHz
PWMPER23 = 1800; //通道23的周期为10KHz
PWMDTY23 = 0; //通道23的占空比设置
PWMDTY45 =900; //通道01的占空比设置 最大1800
PWME_PWME5=1;
PWME_PWME3=1;
}
/**************************************编码器***********************************************/
void TIM_Init1(void)//脉冲累计初始化
{
PACTL=0x50;//下降沿触发kongzhi寄存器
PACNT=0x0000;//清0缓冲寄存器
}
/***************************************************
** 函数名称: main
** 功能描述: 主函数
** 说明:
****************************************************/
void main(void)
{
VSYN_C=0;
DisableInterrupts;
DDRA=0X00; //将PA口设为输入
DDRB=0Xff;//将PB口设为输出
PLL_Init();
SCI_Init();
TIM_Init();
TIM_Init1();
PWM_01();
PWM_35();
/*初始化lcd*/
initial_lcd();
clear_screen();
EnableInterrupts;
PORTA=0X00;
for(;;) //括号内是什么意思啊 死循环可用while(1)替代
{
if(VSYN_C==2)
{
TIE=0x02; //只开场中断?
//xstx() ; //显示图像
yunxing();
VSYN_C=0;
}
jian_su(25); //15指的是什么??目标车速
}
}
本人不发无聊的代码 下载后认真测试评论
尊重他人,尊重自己!!!谢谢!!!
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
|