📄 car_main.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 + -