?? car_main.c
字號:
#include <iom16v.h>
#include <macros.h>
#include "delay.h"
#include "lcd.h"
//調(diào)試使用
uint lcd_i;
uint lcd_j;
uint lcd_k;
//尋線使用
uchar modle_now = 4;
uchar modle_last = 4;
//計圈數(shù)
#define LENGHT_PER_CIRCLE 18 //單位cm , 每個輪子的圈數(shù)
unsigned long int circle = 0; //路程
uchar circle_n_new = 0; //圈數(shù)
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 ); //預(yù)分頻64
}
//設(shè)置pwm_A的占空比
void PwmASet(uint P)
{
OCR1A = P;
}
//設(shè)置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溢出次數(shù)
unsigned long int T2_1s_set_n = 0; //1s次數(shù)
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; //溢出次數(shù)清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; //處部計數(shù)滿10后溢出次數(shù), 周長 = [((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, 用做計算圈數(shù)
#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后如果果再進入中斷,才能使圈數(shù)加1
circle_n_new++;
if (circle_n_new == 4) { //跑了三圈
CarStop(); //小車停止
Time2OnOff(OFF); //關(guān)閉時間計數(shù)器中斷
Time0OnOff(OFF); //關(guān)閉路程計算器
CLI(); //關(guān)所有中斷
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);
//計圈數(shù)使用
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); //小車按鈕開關(guān), 上拉
PORTA |= (1 << PA0);
DDRC |= 0b11110000;
PORTC &=~ 0b01010000;
PORTC |= 0b10100000; //PC口4,5,6,7輸出, 電機停
DDRB &=~ (1 << PB0); //T0做外部計數(shù)
PORTB |= (1 << PB0);
MCUCR = 0x0A; //中斷方式, 都是下降沿
GICR |= (1 << INT1) | (1 << INT0);
//TIMSK = 0x80; //定時器中斷使能
//SEI();
}
#define debug
//主函數(shù)
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);
}
}
}
}
}
}
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -