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

📄 main.c

📁 遥控避障寻线开发板
💻 C
字号:
#include <stdio.h>
#include <intrins.h>
#include "STC12C5202AD.H"
#include "sio.h"

#define MIN9MS (XTAL/2L/256L*9L/1000L*9L/10L)       //9ms脉宽*90%
#define MAX9MS (XTAL/2L/256L*9L/1000L*11L/10L)       //9ms脉宽*110%

#define MIN45MS (XTAL/2L/256L*45L/10000L*9L/10L)       //4.5ms脉宽
#define MAX45MS (XTAL/2L/256L*45L/10000L*11L/10L)

#define MIN225MS (XTAL/2L/256L*225L/100000L*9L/10L)    //2.25ms脉宽
#define MAX225MS (XTAL/2L/256L*225L/100000L*11L/10L)

#define MIN056MS (XTAL/2L/256L*56L/100000L*6L/10L)     //0.56ms脉宽*60%,下限
#define MAX056MS (XTAL/2L/256L*56L/100000L*14L/10L)

#define MIN168MS (XTAL/2L/256L*168L/100000L*6L/10L)   //1.68ms脉宽*60%
#define MAX168MS (XTAL/2L/256L*168L/100000L*14L/10L)

sfr ISP_CUNTR = 0xE7;

sbit LED1 = P3^0;
sbit LED2 = P3^1;

sbit AD_LED1 = P2^0;
sbit AD_LED2 = P2^1;
sbit AD_LED3 = P2^7;

sbit IR_FRONT = P3^2;
sbit IR_LEFT = P3^3;
sbit IR_RIGHT = P2^6;
sbit IR_BACK = P3^7;

sbit IR_OUT = P3^5;

sbit MOTO_IN_B1 = P2^5;
sbit MOTO_IN_B2 = P2^4;

sbit MOTO_IN_A1 = P2^3;
sbit MOTO_IN_A2 = P2^2;

static unsigned char ad_datas[8];  //8路光电管采样电压

bit power_stat;
static unsigned char car_stat;  //小车状态:0,停止;1,前进;2,后退;3,左转;4,右转;5,寻线模式;ff,自控避障模式
static unsigned int now;

static unsigned char code led_mod_table[3][20] = {
   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
   {1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0},
   {1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0}
};
unsigned char idata led_mod = 0;
static unsigned char idata led_tick = 0;
static unsigned char idata led_ptr = 0;


static bit test;

static unsigned char tick = 0;
static unsigned char pwm_tick = 0;
static unsigned char pwm = 0;
static unsigned char pwm_left = 0;
static unsigned char pwm_right = 0;
static unsigned char check;

#define IR_SINGAL_DELAY 11    //接收管输出延迟载波数量
#define TEST_PERIOD 1620      //评估周期,这个不同的接收管差别很大.
#define IR_SINGAL_PERIOD 76   //持续发射红外线载波数量
#define IR_VALID_THROLD 70    //判断是否前方有障碍的阀值

/*
#define IR_SINGAL_DELAY 1    //接收管输出延迟载波数量
#define TEST_PERIOD 200      //评估周期,这个不同的接收管差别很大.
#define IR_SINGAL_PERIOD 10   //持续发射红外线载波数量
#define IR_VALID_THROLD 8    //判断是否前方有障碍的阀值
*/
static unsigned char idata front_signal = 0;
static unsigned char idata back_signal = 0;
static unsigned char idata left_signal = 0;
static unsigned char idata right_signal = 0;

static bit front_obj = 0, back_obj = 0, left_obj = 0, right_obj = 0;

/* 
 * PCA中断计数,根据位置判断信号区域和定义,位置0表示初始,1代表引导码信号,2表示引导码间隔,
 * 3表示第一个bit的信号,4表示第一个bit的间隔,以次类推...
 * 更具体见对应的红外线协议.
*/
static unsigned int idata pca_tick;
static unsigned char idata pca_int_count;
static unsigned char data pca_int_total;    /* 根据引导头确定总长度 */
static unsigned int idata period;   /* 红外信号占或空周期计数 */
static unsigned char idata data_buf[6];  /* 红外线协议数据缓冲区 */
static unsigned int idata ccap1;        //PCA0上一次的的计数
static unsigned char idata frame_dog;  //红外帧看门狗,限定时间未接收完成清除工作

static void delay_ms(unsigned int v) {
  unsigned int wait = pca_tick + v / 7 + 1;
  while (wait != pca_tick) {
      PCON |= 0x01;
  }
}

void time0_isr() interrupt 1
{
    tick++;
    if (tick >= pwm_tick)
    {
        tick = 0;

        if (pwm == 0)
        {
            if (pwm_left > 0)
            {
                MOTO_IN_A1 = 0;
                MOTO_IN_A2 = 1;
            } else
            {
                MOTO_IN_A1 = 0;
                MOTO_IN_A2 = 0;
            }
            if (pwm_right > 0)
            {
                MOTO_IN_B1 = 0;
                MOTO_IN_B2 = 1;
            } else
            {
                MOTO_IN_B1 = 0;
                MOTO_IN_B2 = 0;
            }
        } else
        {
            if (pwm == pwm_left)
            {
                MOTO_IN_A1 = 0;
                MOTO_IN_A2 = 0;
            }
            if (pwm == pwm_right)
            {
                MOTO_IN_B1 = 0;
                MOTO_IN_B2 = 0;
            }
        }
        pwm++;
        if (pwm == 100)
            pwm = 0;

    }
}

void time0_initialize(void)
{
    TMOD &= ~0x0F;      /* clear timer 0 mode bits */
    TMOD |= 0x02;       /* put timer 0 into MODE 2 */
    AUXR |= 0x80;       // timer0工作在1T模式
	TH0 = 0;
	TL0 = 0x0;

//    WAKE_CLKO = 0x01;  // T0在P3.4上输出时钟.

    PT0 = 1;            /* 时钟0中断高优先级 */
	TR0 = 1;            //
	ET0 = 1;
}

static void wakeup (void) interrupt 2
{

}


static void pca_isr (void) interrupt 6
{
    unsigned char i, j;

    if (CCF0) {
        CCF0 = 0;   //清PCA1中断标志
        LED1 = IR_BACK;
        LED2 = IR_BACK;
        if (!pca_int_count) {   //第一次收到信号
            if (!IR_BACK) {
                ccap1 = pca_tick * 256 + CCAP0H;
                pca_int_count++;
            }
        } else {                //已经收到一些信号
             period = pca_tick * 256 + CCAP0H - ccap1;
             ccap1 = pca_tick * 256 + CCAP0H;
//com_putchar(period / 256);
//com_putchar(period % 256);

            if (pca_int_count == 1) {
                if (period < MIN9MS || period > MAX9MS) {  //9ms
                    pca_int_count = 0;
                    frame_dog = 0;
                } else
                    pca_int_count++;
            } else if (pca_int_count == 2) {
                if (period > MIN225MS && period < MAX225MS) { //2.25ms
                    pca_int_total = 3;
                    pca_int_count++;
                } else if (period > MIN45MS && period < MAX45MS) { //4.5ms
                    pca_int_total = 67;
                    pca_int_count++;
                } else {
                    pca_int_count = 0;
                    frame_dog = 0;
                }
            } else {
                if (IR_BACK) {
                    if (period > MIN056MS && period < MAX056MS) {  //0.56ms
                        if (pca_int_count >= pca_int_total) {  //帧接收完毕,下面进行有效性分析.
                            if (pca_int_total == 67) { //完整信号,含有引导信号,设备码8bit,设备反码8bit,命令字8bit,命令字反码8bit
                                if ((data_buf[0] ^ data_buf[1] == 0xff) && (data_buf[2] ^ data_buf[3] == 0xff)) {
                                    com_putchar(data_buf[0]);
                                    com_putchar(data_buf[2]);
                                    if (data_buf[0] == 0x40) {
                                        switch (data_buf[2]) {
                                        case 0x5F: //左
                                            if (pwm_left >= 5)
                                            {
                                                pwm_left--;
                                                pwm_right--;
                                            } else
                                            {
                                                pwm_left = 0;
                                                pwm_right = 0;
                                            }

                                            car_stat = 3;
                                            break;
                                        case 0x5B: //右
                                            if (pwm_left < 100)
                                            {
                                                pwm_left += 5;
                                                if (pwm_left > 100) pwm_left = 100;
                                                pwm_right += 5;
                                                if (pwm_right > 100) pwm_right = 100;
                                            }

                                            car_stat = 4;
                                            break;
                                        case 0x5A: //上
                                            car_stat = 1;
pwm_tick++;

                                            break;
                                        case 0x5E: //下
                                            car_stat = 2;
pwm_tick--;
                                            break;
                                        case 0x56: //菜单
                                            car_stat = 0;
pwm_left = 0;
pwm_right = 0;
                                            break;
                                        case 0x0:  //数字0
                                            car_stat = 0xff;
                                            now = pca_tick;
                                            break;
                                        case 0x1:  //数字1
                                            car_stat = 5;
                                            now = pca_tick;
                                            break;
                                        case 0x12: //POWER
                                           // power_stat = ~power_stat;
                                            break;
                                        default:
                                            break;
                                        }
                                    }
                                }
                            } else {                   //重复信号,仅含有引导信号
                            }
                            pca_int_count = 0;
                            frame_dog = 0;
                        } else {
                            pca_int_count++;
                        }
                    } else {
                        pca_int_count = 0;
                        frame_dog = 0;
                    }
                } else {
                    j = (pca_int_count - 3) / 2;
                    i = j / 8;
                    j = j % 8;

                    if (period > MIN168MS && period < MAX168MS) {  //1.68ms
                     //   com_putchar(0x01);
                        data_buf[i] |= (0x01 << j);
                        pca_int_count++;
                    } else if (period > MIN056MS && period < MAX056MS) {  //0.56ms
                     //   com_putchar(0x00);
                        data_buf[i] &= ~(0x01 << j);
                        pca_int_count++;
                    } else {
                        pca_int_count = 0;
                        frame_dog = 0;
                    }
                }
            }
        }
    }

    if (CF) {    //PCA计数溢出中断,19.6608MHZ晶体大约6.7ms溢出
        CF = 0;
        pca_tick++;

        if (led_tick++ >= 10) {
            led_tick = 0;
            if (led_mod_table[led_mod][led_ptr++]) {
                LED1 = 0;
                LED2 = 0;
            } else {
                if (left_obj || right_obj || front_obj || back_obj) {
                    LED1 = 0;
                    LED2 = 0;
                } else {
                    LED1 = 1;
                    LED2 = 1;
                }
            }
            led_ptr %= 20;
        }

        if (pca_int_count) {
            frame_dog++;
            if (frame_dog >= 15) {  //100ms后重新开始分析新的红外线数据包
                pca_int_count = 0;
                frame_dog = 0;
            }
        }
    }
}

void auto_power_down() {
//    delay(30000);
    ISP_CUNTR = 0x20;  //从AP复位并从AP执行
}

void main (void)
{
    unsigned int i;

    P2M0 = 0x3C;   //P2.2~P2.5  强推挽输出
    P3M0 = 0x30;   //P3.4,P3.5强输出.

    P1ASF = 0xff;   //P1.7~P1.0用做AD

    i = 0;

    MOTO_IN_A1 = 0;
    MOTO_IN_A2 = 0;
    MOTO_IN_B1 = 0;
    MOTO_IN_B2 = 0;

    
    EA = 0;

    power_stat = 0;

    time0_initialize();

//    com_initialize ();    /* initialize interrupt driven serial I/O */
//    com_baudrate (14400); /* setup for 14400 baud */
/*
    CMOD = 0x01;          // #00000001B,PCA空闲计数,PCA计数源=Fosc/12,PCA溢出中断(做一个定时器使用)
    CCON = 0x00;          //PCA中断标志清0,PCA停止计数
    CL = 0x0;
    CH = 0x0;

    CCAPM1 = 0x31;        //PCA1上升下降沿捕获
*/

    CMOD = 0x03;          // #00000011B,PCA空闲计数,PCA计数源=fosc/2,PCA溢出中断
    CCON = 0x00;          //PCA中断标志清0,PCA停止计数
    CL = 0x0;
    CH = 0x0;

    CCAPM0 = 0x31;        //PCA0上升下降沿捕获

/*
    CCAPM0 = 0x42;        //PCA0工作模式:8位pwm
    PCA_PWM0 = 0x00;
    CCAP0L = 0x40;        //25%占空比,可调节占空比来调节发射功率.低电平驱动.
    CCAP0H = 0x40;
*/


//    EPCA_LVD = 1;         //允许PCA和低压检测中断  
    ELVD = 1;

    car_stat = 0x00;
    pca_tick = 0;
    pca_int_count = 0;
    frame_dog = 0;


    EA = 1;                         /* Enable Interrupts */
    CR = 1;                         //启动PCA计数

    now = pca_tick;

    while (1)
    {
        PCON |= 0x01;
    }
    
}

⌨️ 快捷键说明

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