📄 +Ҥ
字号:
#include <hidef.h>
#include <MC9S12XS128.h>
#include "UART.h"
#pragma LINK_INFO DERIVATIVE "mc9s12xs128"
unsigned short int chesudu;
#define turn_max 450 //最大转角对应的PWM值,最大的转角
#define straight 3300 //直走的SteerPWM 也即是 1.5ms 宽度 调整机械,使机械居中 3999
int pos_;
//采集到的数据在二维数组ta[lie][hang_end]里;
//接口定义: 行同步接PT2 场同步接PT1 信号线是接A0
//串口波特率为57600 USB转TTL串口的RX接单片机的S1 观察数据
//------------------------------------------------
#define lie_end 260
#define hang_end 90 //这里只每行采多少个点 根据像素来 最右边采到0表示采多了减少该值。
#define lie 32//51
#define delay(num) \
{ \
unsigned int i,j; \
for(i=0;i<num;i++) \
for(j=0;j<58;j++); \
}
//延时去消隐信号。 最左边有0表示采到消隐了增加J
unsigned char c_lie=0,g_lie=0;
unsigned int lie_count=0,hang_count=0;
unsigned int lie_uart=0,hang_uart=0;
unsigned char ta[lie][hang_end];
unsigned int get_n[]={ 29,41,52,62,71,79,86,92,98,
103,108,112,116,120,124,128,132,135,138,
141,144,147,150,153,156,159,162,165,168,
170,172,174,176,178,180,182,184,186,188,
190,192,194,196,198,200,202,204,206,208,
210,211,212,242,243,245,246,247,248,249,250}; //定每场采哪几行。 根据像素决定。上面下面采到0了说明超出像素了。
#define uchar unsigned char
#define uint unsigned int;
void chaopin(void);
void TIM_init(void);
void shijian(void);
void atd_init(void);
void pwm_init(void);
void Pos_cal(void)
{
unsigned char i;
char num_on=0;
int i_sum;
/////////////////////////////////////////////////////////
num_on = 0;//获得压线传感器的个数 num_on,
i_sum =0;//压线传感器的标号(0~14)之和
for(i=0; i<=89; i++)
{
if(ta[16][i]==1)//有一个压线 黑线=1
{
num_on = num_on + 1; //压线传感器的个数
i_sum = i_sum + (45-i); //压线传感器的标号(0~14)之和
}
}
if(num_on!=0) //监测到有传感器压线
{
pos_ = i_sum/num_on; //重心
}
else//没有一个压线,则跑飞,保持上一次的位置。
{
pos_=pos_;
}
}
void main(void)
{
int temp_=0;
DDRA=0X00;
DDRJ=0X02;
DDRK=0X30;
PTJ_PTJ1=1;//RS 0输入指令 1输入数据
PORTK_PK5=1; //R/W 0向lcd输入指令或数据、1从lcd读取数据
PORTK_PK4=1; //E 使能信号 1读取信息 1到0的下降沿执行指令
DisableInterrupts;
{
chaopin();
atd_init();
TIM_init();//计数器函数初始化
shijian();
pwm_init();
uart_init();
delay(900) ;
EnableInterrupts;
{
unsigned int e,w;
for(e=1;e<6;e++)
for(w=0;w<10;w++);
}
}
for(;;)
{
Pos_cal();
if(pos_<10&pos_>-10)
pos_=0;
temp_ = straight - 20*(pos_); //如果转向正好相反,就改成: straight + (Kp[abs(pos_)])*(pos_);特别注意!!!
//temp_ = straight; //测试居中语句
if(temp_ <= straight-turn_max)//最大转角保护
{
temp_ = straight-turn_max;
}
else if(temp_ >= straight+turn_max)//最大转角保护
{
temp_ = straight+turn_max;
}
else
{
temp_ = temp_;
}
PWMDTY23 = temp_;
for(hang_uart=0;hang_uart<=99;hang_uart++) { //用串口观察。根据上面hang_end改这里
printp("%d",ta[16][hang_uart]);
{
unsigned int e,w;
for(e=1;e<60;e++)
for(w=0;w<100;w++);
}
}
printp("\n");
}
}
void chaopin(void)
{
CLKSEL=0X00;
PLLCTL_PLLON=1;
SYNR =0xc0 | 0x07;
REFDV=0xc0 | 0x01;
POSTDIV=0x00;
_asm(nop);
_asm(nop);
_asm(nop);
_asm(nop);
while(!(CRGFLG_LOCK==1));
CLKSEL_PLLSEL =1;
}
void atd_init(void)
{
ATD0CTL1=0x00;
ATD0CTL2=0X40; //禁止中断 转换后自动清除寄存器
ATD0CTL3=0X88; //没有断点 没有FIFO 通道0开始 单通道 继续转换右对齐 转换序列1
ATD0CTL4=0X00; //4周期,64/2,最快
ATD0CTL5=0X30; // 连续转换 多通道转换 通道AN0开始
ATD0DIEN=0x00; //相应的数字信号输入禁止
}
void TIM_init(void)
{
PACTL=0X50;
PACNT=0X0000;
TIOS =0x00;//定时器通道0,1 为输入捕捉
TSCR1=0x80;//定时器使能
TCTL4=0x18;//通道 1 捕捉下降沿通道 2 捕捉上升沿
TIE=0x06; //通道 1,2 中断使能
TFLG1=0xFF;//清中断标志位
}
void shijian(void) {
PITCFLMT_PITE=0;
PITCE_PCE0=1;
PITLD0=9999; //1 毫秒
PITMTLD0=5;
PITMUX=0X00;
PITINTE_PINTE0=1;
PITCFLMT_PITE=1;
}
void pwm_init(void)
{
/********PTTRR *****************************
7 6 5 4 3 2 1 0
PTTRR7 PTTRR6 PTTRR5 PTTRR4 0 PTTRR2 PTTRR1 PTTRR0
PWM7 PWM6 PWM5 PWM4 0 IOC2 IOC1 IOC0
复位值 0 0 0 0 0 0 0 0
选择从哪个端口输出
0->PP7 0->PP6 0->PP5 0->PP4 0->PP2 0->PP1 0->PP0
1->PT7 1->PT6 1->PT5 1->PT4 1->PT2 1->PT1 1->PT0
**********PTTRR *****************************************/
// PTTRR = 0x00; //选择PWM与IOC的端口:PWM对应PP口,IOC对应PT口
PWME=0x00; //禁止PWM模块
/* ************ PWMCTL 级联和工作模式控制寄存器 **************
7 6 5 4 3 2 1 0
CON67 CON45 CON23 CON01 PSWAI PFRZ 0 0
复位状态 0 0 0 0 0 0 0 0
*******************PWMCTL***************************************/
PWMCTL_CON23=1; // 二三两个八位的通道结合成十六位的通道从三通道输出
// 4高字节,5低字节;5的输出脚作为组合后的输出脚,
// 由5来时钟选择,使能,极性控制组合后的特性。
/************* PWMCLK 时钟选择寄存器 ***************************
7 6 5 4 3 2 1 0
PCLK7 PCLKL6 PCLK5 PCLK4 PCLK3 PCLK2 PCLK1 PCLK0
复位状态 0 0 0 0 0 0 0 0
0->B 0->B 0->A 0->A 0->B 0->B 0->A 0->A
1->SB 1->SB 1->SA 1->SA 1->SB 1->SB 1->SA 1->SA
*****************PWMCLK*************************************************/
PWMCLK=0x00; //
/***************PWMPRCLK 设置A B 时钟分频*************************
----------------------------------------------------------
7 6 5 4 3 2 1 0
* PCKB2 PCKB1 PCKB0 * PCKA2 PCKA1 PCKA0
Reset 0 0 0 0 0 0 0 0
---------------------------------------------------------
PCKB2 PCKB1 PCKB0 Value of Clock B PCKA2 PCKA1 PCKA0 Value of Clock A
0 0 0 Bus clock 0 0 0 Bus clock
0 0 1 Bus clock / 2 0 0 1 Bus clock / 2
0 1 0 Bus clock / 4 0 1 0 Bus clock / 4
0 1 1 Bus clock / 8 0 1 1 Bus clock / 8
1 0 0 Bus clock / 16 1 0 0 Bus clock / 16
1 0 1 Bus clock / 32 1 0 1 Bus clock / 32
1 1 0 Bus clock / 64 1 1 0 Bus clock / 64
1 1 1 Bus clock / 128 1 1 1 Bus clock / 128
***************PWMPRCLK*********************************************************************/
PWMPRCLK=0x55; // 时钟预分频寄存器 ,时钟 B 频率为 Bus Clock/32 ,时钟 A 频率为 Bus Clock/32
PWMSCLA=0x06; // SA 时钟分频寄存器 Clock SA=Clock A/(2 * PWMSCLA) = Bus Clock/(32*2*6 =96) 384
PWMSCLB=0x06; // SB 时钟分频寄存器 Clock SB=Clock B/(2 * PWMSCLB) = Bus Clock/(2*2*6 =96)= 64/24=2.666M
PWMPOL=0x3f; // PWMPOL_PPOL0=1--- 通道 0 在周期开始时输出为高电平,当计数器等于占空比寄存器的值时,输出为低电平。对外输出波形先是高电平然后再变为低电平
// PWMCAE=0x00; //左对齐和中间对齐设置寄存器默认都为左对齐。
PWMPER0=255; // 周期设置寄存器 , 赋的数值即为每一个周期包含的时钟数 , bus Mhz/384
// 脉冲数设为200时,电机 8bit 频率为: 1khz 64/32=2M(2000K);0.0005*250=0.125;1/0.125=8KHZ
//左对齐输出频率=Clock (A, B, SA, or SB) / PWMPER 因此这里输出频率=64M/32/250=8K
//右对齐输出频率=Clock (A, B, SA, or SB) / (2*PWMPER)
PWMDTY0=90; // 占空比设置寄存器 , 赋的数值即为每一个周期内高电平所占的时钟数
// 左对齐占空比= [(PWMPER-PWMDTY)/PWMPER] * 100%
//右对齐占空比= [PWMDTY / PWMPER] * 100%
PWMPER1=255;
PWMDTY1=0; // 通道 1 输出一直为低低电平 , 和通道 0 形成电压差 , 用于驱动电机
PWMPER4=255; //因此这里输出频率=80M/32/250=8K
PWMDTY4=90; // 左对齐占空比= [(PWMPER-PWMDTY)/PWMPER] * 100%
PWMPER5=255;
PWMDTY5=0; // 通道 5 输出一直为低低电平 , 和通道 4 形成电压差 , 用于驱动电机
// 2,3 选用通道3作为最后的输出,通道3默认使用时钟 B 为 32 分频
PWMPER23 = 40000; // 周期为 20ms, 总线时钟为 64Mhz 32分频 40000*(1/2000) =20MS
//PWMPER45 = 25000; // 周期为 20*0.5ms, 总线时钟为:80Mhz 32分频
//PWMPER45 = 10000; // 周期为 20*0.2ms, 总线时钟为:80Mhz 32分频
PWMDTY23 = straight; // 为了设定占空比为 1.5ms , 直线前进
/*///////////////////////////////////////////////////////////////
// PWME 通道使能寄存器
7 6 5 4 3 2 1 0
PWME7 PWME6 PWME5 PWME4 PWME3 PWME2 PWME1 PWME0
复位状态 0 0 0 0 0 0 0 0
///////////////////////////////////////////////////////////////*/
// PWME=0x3f; // 通道使能寄存器 , 电机 0,1 4,5 通道 , 舵机 3 通道使能
PWME_PWME0 = 1; // 前进pwm
PWME_PWME1 = 1;
PWME_PWME4 = 1; // 前进pwm
PWME_PWME5 = 1;
PWME_PWME3 = 1;
}
//---------------------------------
//=======图像采集中断函数,已经完全可以采集图像的=========
#pragma CODE_SEG NON_BANKED
void interrupt 10 IC2ISR(void) { //行中断
TFLG1_C2F=1;
if(lie_count==get_n[c_lie]) { //定距采集图像的判断条件
delay(1); //黑线中心矫正,确保不采集到消隐信号
for(hang_count=0;hang_count<=hang_end;hang_count++){ //读取一行的数据
ta[c_lie][hang_count]=PORTA_PA0; //采集数据的接口
}
c_lie++; //二维数组行自加
}
lie_count++; //摄像头行自加
}
void interrupt 9 IC1ISR(void){ //场中断,各数据清零
TFLG1_C1F=1;
hang_count=0;
lie_count=0;
c_lie=0;
}
void interrupt 66 PIT0Interrupt(void) //测速的中断程序
{
chesudu=PACNT; //车速度值
PITTF_PTF0=1;
PACNT=0X0000;
}
#pragma CODE_SEG DEFAULT
//接脚是行同步接pt2 场同步接pt1
//如果数组ta[c_lie][hang_count]没有图像,请检查接线的问题,以及接口是否按我们所说的接口。
//感谢你对手创科技的支持和信任,我们将不断的努力争取做得更好。
//如果有什么问题,欢迎咨询我们的技术人员。在程序首段有我们的联系方式。
//衷心祝愿我们的客户取得好的成绩!
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -