找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3550|回复: 13
打印 上一主题 下一主题
收起左侧

做一个蓝牙小车程序,pwm中断和串口中断冲突,有大哥帮帮忙吗,看看那里有问题

  [复制链接]
跳转到指定楼层
楼主
ID:344179 发表于 2019-2-25 15:04 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
有大哥帮帮忙吗,看看那里有问题,51单片机做一个蓝牙小车程序,pwm中断和串口中断冲突,帮忙看看那里有问题, 感谢感谢。


#include <reg52.h>

sbit EN1 = P2^0; //为1 右电机使能
sbit EN2 = P2^1; //为1 左电机使能
sbit IN1 = P2^2; //为1 右电机反转
sbit IN2 = P2^3; //为1 右电机正转
sbit IN3 = P2^4; //为1 左电机正转
sbit IN4 = P2^5; //为1 左电机反转

#define left_motor_en           EN1 = 1           //左电机使能
#define left_motor_stops        EN1 = 0           //左电机停止
#define right_motor_en          EN2 = 1           //右电机使能
#define right_motor_stops       EN2 = 0           //右电机停止
#define left_motor_go           IN1 = 0, IN2 = 1  //左电机正传
#define left_motor_back         IN1 = 1, IN2 = 0  //左电机反转
#define right_motor_go          IN3 = 1, IN4 = 0  //右电机正传
#define right_motor_back        IN3 = 0, IN4 = 1  //右电机反转

double count = 0;//定义占空比,并初始占空比为26%
unsigned char time;
unsigned char pwm_left_val = 0;//左电机占空比值 取值范围0-170,0最快
unsigned char pwm_right_val = 0;//右电机占空比值取值范围0-170 ,0最快
unsigned char pwm_t; //周期

void UART_INIT();  //蓝牙接收初始化
void Che_init();   //小车输出端口定时器初始化
void forward();    //小车前进
void back();       //小车后退
void right();      //小车左转
void left();       //小车右转
void stop();           //小车停止
void delay(unsigned int z);        //延时函数
               
void main()
{
        UART_INIT();  //蓝牙接收初始化
    Che_init();          //小车输出端口定时器初始化
    while(1);
        

}

void UART_INIT()  //蓝牙接收初始化
{
        SCON = 0X50;
    TMOD = 0x20; //8位自动重装模式
    TH1 = 0xfd;
    TL1 = 0xfd;  //9600波特率
    TR1 = 1;     //启动定时器1
    ES = 1;      //开串口中断
        EA = 1;      //开总中断
}
                        
void Che_init()         //小车使能输出端口定时器初始化
{
        TMOD|= 0x02; //8位自动重装模块
        TH0=(65536-10)/256;
        TL0=(65536-10)%256;
        TR0=1;
        ET0=1;
        EA=1;
/*
        TMOD|= 0x02; //8位自动重装模块
    TH0 = 220;
    TL0 = 220;    //11.0592M晶振下占空比最大比值是256,输出100HZ
    TR0 = 1;      //启动定时器0
    ET0 = 1;      //允许定时器0中断
    EA = 1;       //总中断允许
        */
}

void forward()        //小车前进
{
        ET0 = 1;
        TR0 = 1;
    left_motor_go;  //左电机前进
    right_motor_go; //右电机前进
        while(1)
        {
                count += 0.1;
        }
}

void back()        //小车后退
{
        ET0 = 1;
        TR0 = 1;
        left_motor_back;  //左电机反转
        right_motor_back; //右电机反转      
}

void right()  //小车左转
{
        ET0 = 1;
        TR0 = 1;
        left_motor_go;    //左电机正传
        right_motor_back; //右电机反转
}

void left()          //小车右转
{
        ET0 = 1;
        TR0 = 1;
        right_motor_go;         //右电机正传
        left_motor_back; //左电机反转
}

void stop()          //小车停止
{
        ET0 = 0;
        TR0 = 0;
        count = 0;
        left_motor_stops;   //左电机停止
        right_motor_stops;        //右电机停止
}

void timer0() interrupt 1  //定时器0中断
{  
        TR0 = 0; //设置定时器初值期间,关闭定时器
        TH0=(65536-10)/256;
        TL0=(65536-10)%256;
        //TR0=1;
        time++;
        //count += 0.1;
        if(time<count)
        {        
                EN1 = 1;  //输出高电平
                EN2 = 1;  //输出高电平
        }
        else
        {
                EN1 = 0;  //输出低电平
                EN2 = 0;  //输出低电平
        }
        if(time>=1000)
                time=0;
                /*
        pwm_t++;
        if(pwm_t == 255)
        {
           EN1 = 0;
           EN2 = 0;
           pwm_t = 0;
        }
        if(pwm_left_val == pwm_t)
            EN1 = 1;
        if(pwm_right_val == pwm_t)
                EN2 = 1;*/                        
}


void UART_SER() interrupt 4  //串口中断
{
        if(RI)
    {
            RI = 0;//清除接收标志
        switch(SBUF)
        {
                case 'a':          //前进
                                forward();
                                break;
            case 'b':          //后退
                                back();
                                break;
            case 'l':          //左转
                                right();
                                break;
                        case 'r':          //右转
                                left();
                                break;
            case 's':          //停止
                                stop();
                                break;
                        default:     //否则全部停止
                                stop();
                                break;
        }
     }
}

void delay(unsigned int z)
{
        unsigned int x,y;
        for(x = z; x > 0; x--)
                for(y = 114; y > 0 ; y--);
}


评分

参与人数 1黑币 +2 收起 理由
kljie1000 + 2

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶2 踩
回复

使用道具 举报

沙发
ID:158375 发表于 2019-2-25 16:44 | 只看该作者
程序没看,只是想问一下:
你是怎么确认的PWM中断和串口中断有冲突呢?
回复

使用道具 举报

板凳
ID:344179 发表于 2019-2-25 21:27 | 只看该作者
笨笨兔 发表于 2019-2-25 16:44
程序没看,只是想问一下:
你是怎么确认的PWM中断和串口中断有冲突呢?

只有pwm在动作 蓝牙串口不工作,卡在前进的while()中了,要的效果是,小车前进pwm从0到最大
回复

使用道具 举报

地板
ID:432823 发表于 2019-2-26 08:01 | 只看该作者
中断嵌套,优级高占先,定时器0高于定时器1,定时器0定时值太小,很快就中断,造成始终定时器中断,PWM有动作,串口无法中断接收。
回复

使用道具 举报

5#
ID:164602 发表于 2019-2-26 08:20 | 只看该作者
卡这里了:
        while(1)
        {
                count += 0.1;
        }
这里死循环,当然卡住了嘛。
回复

使用道具 举报

6#
ID:158375 发表于 2019-2-26 08:36 | 只看该作者
你在串口中断里直接处理SBUF,那么定时器0中断怎么进去呢?
我认为是你的程序结构或框架问题,改变思路试一试吧;
串口中断里把SBUF保存起来,在while()处理那个数据,可能会好些吧。
一般情况下,中断里面,做最少的事情,只做必要的。需要处理,把标志位保存即可,剩下的事情让主程序去干!
回复

使用道具 举报

7#
ID:344179 发表于 2019-2-26 15:04 | 只看该作者
yaoji123 发表于 2019-2-26 08:01
中断嵌套,优级高占先,定时器0高于定时器1,定时器0定时值太小,很快就中断,造成始终定时器中断,PWM有动 ...

大哥 ,能改成pwm从0到最大吗
回复

使用道具 举报

8#
ID:480013 发表于 2019-3-9 16:55 | 只看该作者
张事坤 发表于 2019-2-26 15:04
大哥 ,能改成pwm从0到最大吗

这是可以的,如果不正常你再把周期改小一点
回复

使用道具 举报

9#
ID:469417 发表于 2019-3-9 22:13 | 只看该作者
你是怎么确认的PWM中断和串口中断有冲突,建议分开调试检查

评分

参与人数 2黑币 +22 收起 理由
春风十里吹 + 12 回帖助人的奖励!
zhengchong60 + 10 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

10#
ID:466164 发表于 2019-3-9 23:05 | 只看该作者
赞同HC6800-ES-V2.0
while(1)
        {
                count += 0.1;
        }
这里死循环,只要小车前进,程序没有跳出死循环语句,程序就一直跳不出,别的程序别想工作。
回复

使用道具 举报

11#
ID:137676 发表于 2019-3-10 00:55 | 只看该作者
感觉你定时器时间太短了
回复

使用道具 举报

12#
ID:478236 发表于 2019-3-10 08:11 | 只看该作者
上次我做过这个小车,后来发现串口接受一点问题都没有,就是定时器中断只进入一次,第二次就进不去,不懂你现在是不是这个问题?
回复

使用道具 举报

13#
ID:213173 发表于 2019-3-10 08:58 | 只看该作者
你定时器中断设定10us,完成一次定时中断内容需要300us,怎么可能正常工作。何况在前进程序中使用死循环,结果是同归于尽,大家一起死。
回复

使用道具 举报

14#
ID:467843 发表于 2019-4-2 13:33 | 只看该作者
while(1)
         {
                 count += 0.1;
         }
}
前进程序干嘛要加while ,可以删掉的。
还有你那定时至少100us啊,10us太短暂。
另外你你这个程序框架设计给我的感觉有点不简洁。
count += 0.1;这个你想表达什么意思呢
定义变量可以像我这么定义,用数组比较简洁。
#define Left_moto_Stop    {P1_0=0;P1_1=0,P1_2=0;}    //左电机停转
#define Left_moto_go      {P1_0=1;P1_1=1,P1_2=0;}    //左电机正转
#define Left_moto_back    {P1_0=1;P1_1=0,P1_2=1;}          //左电机反转
#define Right_moto_Stop   {P1_3=0;P1_4=0,P1_5=0;}           //右电机停转                     
#define Right_moto_go     {P1_3=1;P1_4=1,P1_5=0;}           //右电机正转
#define Right_moto_back   {P1_3=1;P1_4=0,P1_5=1;}           //右电机反转

引脚定义自己改


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表