⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 car_main.c

📁 基于m16的寻迹小车(包含小车题目
💻 C
字号:
#include <iom16v.h>
#include <macros.h>
#include "delay.h"
#include "lcd.h"

//调试使用
uint lcd_i;
uint lcd_j;
uint lcd_k;

//寻线使用
uchar modle_now = 4;
uchar modle_last = 4;

//计圈数
#define LENGHT_PER_CIRCLE  18 //单位cm , 每个轮子的圈数

unsigned long int circle = 0; //路程
uchar circle_n_new = 0;       //圈数
uchar circle_n_old = 0;
uchar getlinestart = 0;       //碰到起跑线
long int nextint_time = 0;    //下次起跑线取值的时间

unsigned long int Light_time = 0;     //遇到一圈时,响一下,由此计时
uchar light_set_flag = 0;


#define ON  1
#define OFF 0

#define PWMA_HIG_VAL 110 //A电机高速时占空比, hight speed  注意,使用的是8位快速模式
#define PWMB_HIG_VAL 110
#define PWMA_LOW_VAL 1			   	 	//A电机低速时占空比  low   speed 
#define PWMB_LOW_VAL 1

#define PWMA_MID_VAL 165//A电机中速时点空比  midlle speed 
#define PWMB_MID_VAL 165

#define PWMB_MAX_VAL 1023  //最大占空比         max speed
#define PWMB_MAX_VAL 1023
#define PWMA_MIN_VAL 0    //最小占空比         min speed
#define PWMB_MIN_VAL 0

void closeJTAG(void)//   1JTAG
{MCUCSR|=0X80; MCUCSR|=0X80;}

/*-------------------------------PWM----------------------------------*/	
void PwmInit (void)
{
	//T1 for PWM
 	DDRD |= ( 1 << PD4 ) | ( 1 << PD5 );
 	TCCR1A = ( 1 << WGM11 ) | ( 1 << WGM10 ) | ( 1 << COM1A1 ) | ( 1 << COM1B1 ); //匹配清0,两路10位相位修正PWM
 	TCCR1B = ( 0 << CS12 ) | ( 1 << CS11 ) | ( 1 << CS10 ); //预分频64	
}

//设置pwm_A的占空比
void PwmASet(uint P)
{
	OCR1A = P;	
}

//设置pwm_B的占空比
void PwmBSet(uint P)
{
	OCR1B = P;	
}

/*------------------------------------PWM END----------------------------------------*/

/*------------------------------------car active----------------------------------------*/
//全速向前
void CarGoAheadFullSpeed (void)
{
	PwmASet(PWMA_HIG_VAL);
	PwmBSet(PWMB_HIG_VAL);
}

//中速向前
void CarGoAheadMidSpeed(void)
{
	PwmASet(PWMA_MID_VAL);
	PwmBSet(PWMB_MID_VAL);	
}

//向左
void CarTurnLeft (void)
{
	//TCNT1 = 0x3fe;
	PwmASet(PWMA_LOW_VAL);
	PwmBSet(PWMB_HIG_VAL);
}

//向右
void CarTurnRight (void)
{
	//TCNT1 = 0x3fe;
	PwmASet(PWMA_HIG_VAL);
	PwmBSet(PWMB_LOW_VAL);
}

//停止
void CarStop (void)
{
	//TCNT1 = 0x3fe;
	PwmASet(PWMA_MIN_VAL);
	PwmBSet(PWMB_MIN_VAL);
}

//--------------------------------------------声光报警
void LightOnOff (uchar onoff)
{
	DDRC |= (1 << PC0);
	
	if (onoff == OFF) {
		PORTC &=~ (1 << PC0);
	}

	else if (onoff == ON) {
		PORTC |= (1 << PC0);
	}		
}

/*------------------------------------end car active ----------------------------------------*/

/*------------------------------------TIME ----------------------------------------*/
uchar T2_int_n = 0;    //定时器25ms溢出次数
unsigned long int T2_1s_set_n = 0; //1s次数
uchar T2_1s_set = 0;


//TIMER2 initialize - prescale:1024
// WGM: CTC
// desired value: 25mSec
// actual value: 25.088mSec (0.4%)
void timer2_init(void)
{
 TCCR2 = 0x00; //stop
 ASSR  = 0x00; //set async mode
 TCNT2 = 0x3D; //setup
 OCR2  = 0xC3;
 TCCR2 = 0x0F; //start
}

#pragma interrupt_handler timer2_comp_isr:iv_TIM2_COMP
void timer2_comp_isr(void)
{
 //compare occured TCNT2=OCR2
 //compare occured TCNT0=OCR0
	if((T2_int_n++) == 40) {  //25ms溢出, 40次则1s
		T2_1s_set = 1;
		T2_1s_set_n ++;  //置位1s
		T2_int_n = 0;  //溢出次数清0
	}
}


//计时开始停止控制
void Time2OnOff (uchar onoff)
{
	if (onoff == ON) {
		TIMSK |= (1 << OCIE2);  //开时间中断
	}

	else if (onoff == OFF) {
		TIMSK &=~ (1 << OCIE2);  //禁止时间中断
	}		
}

//-----------------------T0------------------------------------
unsigned long int T0_10_n = 0;  //处部计数满10后溢出次数, 周长 = [((10 * T0_10_n) + TCNT0) / 5 ]* LENGHT_PER_CIRCLE
uchar T0_10_set = 0;
//TIMER0 initialize - prescale:Falling edge
// WGM: CTC
// desired value: 1Hz
// actual value: Out of range
void timer0_init(void)
{
 TCCR0 = 0x00; //stop
 OCR0  = 9 /*INVALID SETTING*/;  //set compare
 TCCR0 = 0x0E; //start timer
}

#pragma interrupt_handler timer0_comp_isr:iv_TIM0_COMP
void timer0_comp_isr(void)
{
 //compare occured TCNT0=OCR0
 	T0_10_n++;
 	T0_10_set = 1;
 	//LCD_write_datalongint(1, 10, T0_200_n);
}

//计周长开始停止控制, 影响中断使能
void Time0OnOff (uchar onoff)
{
	if (onoff == ON) {
		TIMSK |= (1 << OCIE0);  //开时间中断
	}

	else if (onoff == OFF) {
		TIMSK &=~ (1 << OCIE0);  //禁止时间中断
	}		
}


/*------------------------------------TIME END----------------------------------------*/

/*-------------------------------int0 & int1----------------------------------*/

//中断1, 用做计算圈数
#pragma interrupt_handler int1_isr:iv_INT1
void int1_isr(void)
{	
	//GICR &=~ (1 << INT1);
 	//external interupt on INT1
	//getlinestart = 1;
	if (T2_1s_set_n >= nextint_time) {
	   	getlinestart = 1;
		nextint_time += 13; //10s后如果果再进入中断,才能使圈数加1
		circle_n_new++;
		
		if (circle_n_new == 4) {  //跑了三圈
			CarStop();           //小车停止
			Time2OnOff(OFF);     //关闭时间计数器中断
			Time0OnOff(OFF);     //关闭路程计算器			
			CLI();               //关所有中断
		
			LightOnOff(ON);      //灯闪
			delay_ns(1);
        	LightOnOff(OFF);
			delay_ns(1);

			while (1) {;}        //死车
		}
	}
	
	//LCD_write_datalongint(1, 10, lcd_i++);
	//if(lcd_i == 5)
	//	GICR &=~ (1 << INT1);
}

//扩展中断0, 用做寻线
#pragma interrupt_handler int0_isr:iv_INT0
void int0_isr(void)
{
 	//external interupt on INT1
 	switch( PIND & 0b01000111 ) {			
		case 0b01000010: //左红外遇到黑线
		case 0b01000000: //左中遇到
			modle_now = 1;			
			break;
			
		case 0b01000001: //中红外遇到黑线
			modle_now = 2;
			break;

		case 0b00000011: //右红外遇到黑线
		case 0b00000001: //右中遇到
			modle_now = 3;
			break;

		default :
			modle_now = 4;
			break;
	} 	
}

//小车寻线
void CarFindLine (void)
{
	if (modle_last == 1) {
		CarTurnLeft();
		
		switch (modle_now) {
			case 2:
				modle_last = 4;
				break;

			case 3:
				modle_last = 3;
				break;

			default :
				break;
		}
	}

	else if (modle_last == 3) {
		CarTurnRight();
		
		switch (modle_now) {
			case 1:
				modle_last = 1;
				break;

			case 2:
				modle_last = 4;
				break;

			default :
				break;
		}
	}					
	
	else if (modle_last == 4) {
		CarGoAheadMidSpeed(); 

		switch (modle_now) {
			case 1:
			case 3:
				modle_last = modle_now;
				break;

			default :
				break;
		}
	}
}
/*-------------------------------end---------------------------------------------*/

//call this routine to initialize all peripherals
void init_devices(void)
{
 	//stop errant interrupts until set up
	closeJTAG();
 	CLI(); //disable all interrupts

	//时间使用
	timer2_init();
	Time2OnOff(OFF);

	//计圈数使用
	timer0_init();
	Time0OnOff(OFF);

	//lcd
 	LCD_init();

	//pwm
	PwmInit();
	PwmASet(PWMA_MIN_VAL);
	PwmBSet(PWMB_MIN_VAL);
 
 	//INT1:0
	DDRD &=~ (1 << PD0) | (1 << PD1) | (1 << PD2) | (1 << PD3) | (1 << PD6); //PD口的0,1,6做扩展中断, 2,3做中断
	PORTD |= (1 << PD0) | (1 << PD1) | (1 << PD2) | (1 << PD3) | (1 << PD6);

	DDRA &=~ (1 << PA0);  //小车按钮开关, 上拉
	PORTA |= (1 << PA0);

	DDRC  |=  0b11110000;
	PORTC &=~ 0b01010000;
	PORTC |=  0b10100000; //PC口4,5,6,7输出, 电机停

	DDRB &=~ (1 << PB0);  //T0做外部计数
	PORTB |= (1 << PB0);
	
 	MCUCR = 0x0A;  //中断方式, 都是下降沿	
	GICR |= (1 << INT1) | (1 << INT0); 	
 
	//TIMSK = 0x80; //定时器中断使能
 	//SEI();
}

#define debug
//主函数
void main(void)

{		
	init_devices();

	LCD_write_string(1, 4, "Good luck");
	LCD_write_string(2, 0, "made on 09-05-01");
		
	#ifdef debug
	LightOnOff(ON);
	delay_nms(200);
	LightOnOff(OFF);
	delay_nms(200);
	#endif
	
	//while(1) {;}  
	
    while(1){		
		if ((PINA & (1 << PA0)) == 0 ) {  //等待按下开始键	
			SEI(); //打开全局中断
			
			CarGoAheadMidSpeed();  //小车向前		
			while (1) {
				CarFindLine();     //小车寻线
				
				if (getlinestart == 1) { //如果遇到起跑线
					LCD_write_string(1, 0, "                   ");
					LCD_write_string(2, 0, "                   ");
					LCD_write_string(1, 0, "circle:      cm ");
					LCD_write_string(2, 0, "time  : 0    s ");
					
					Time0OnOff(ON); //开始计算路程
					Time2OnOff(ON); //开始计时
					
					while (1) {
						CarFindLine(); //寻线

						if (T2_1s_set == 1) { //显示时间
							LCD_write_datalongint(2, 8, T2_1s_set_n);
							T2_1s_set = 0;
						}

						if (T0_10_set == 1) {  //显示路程
							circle = (((10 * T0_10_n) + TCNT0) / 5) * LENGHT_PER_CIRCLE;
							LCD_write_datalongint(1, 8, circle);
							T0_10_set = 0;
						}
						
						if (circle_n_new != circle_n_old) {
						   LCD_write_datalongint(1, 15, circle_n_new);
						   circle_n_old = circle_n_new;

						   LightOnOff(ON);
						   light_set_flag = 1;
						   Light_time = 0;
						}

						if ((light_set_flag == 1) && (Light_time++) >= 5000) {
							light_set_flag = 0;
							LightOnOff(OFF);
						}								
					}
				}			
			}
		}
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -