李鸿鸿 发表于 2013-5-3 12:08:13

用STC12C5A60S2做的智能小车出现问题(PWM)

本人正在做智能小车,用STC12C5A60S2单片机(晶振27MHZ),硬件已经搭建好了,编程中发现了一个非常重要的问题,2路PWM输出IO口不对,不是PWM输出脚,接到了P2口,而PWM输出脚已经被其它占用,不能移动的,反正硬件已经固定了。
2个检测信号,1个蜂鸣器,1个无线发射和接收(nRF24L01),还有一个液晶显示,共加起来有7个任务,这么多任务,怎么安排?能移入操作系统吗?
就算能移入操作系统,那2路PWM输出怎么办?用延时?用定时?
求高手指教,给个建议或者给个思路,或者给个程序

李鸿鸿 发表于 2013-5-3 12:09:54

先顶一下

380999494 发表于 2013-5-3 13:39:13

割板嘛,基本没啥电路是改不了的

chenrulin 发表于 2013-5-3 13:42:16

模拟PWM。   

李鸿鸿 发表于 2013-5-3 13:46:30

chenrulin 发表于 2013-5-3 13:42 static/image/common/back.gif
模拟PWM。

怎么个模拟法呢?

李鸿鸿 发表于 2013-5-3 13:47:52

chenrulin 发表于 2013-5-3 13:42 static/image/common/back.gif
模拟PWM。

void Output2(uint x)//PWM1输出控制右边电机
{
        static uchar i;
        ;;
        for(i=0;i<10;i++) //
        {
                m3=1;
                delay2(x);
                m3=0;
                delay2(100-x); //百分比
        }
}

李鸿鸿 发表于 2013-5-3 13:48:58

chenrulin 发表于 2013-5-3 13:42 static/image/common/back.gif
模拟PWM。

7个任务哦?

李鸿鸿 发表于 2013-5-3 13:50:13

380999494 发表于 2013-5-3 13:39 static/image/common/back.gif
割板嘛,基本没啥电路是改不了的

有没有能用软件实现的呢?

lcw_swust 发表于 2013-5-3 17:06:21

http://www.amobbs.com/forum.php?mod=viewthread&tid=5039835&highlight=%E6%97%B6%E9%97%B4%E8%A7%A6%E5%8F%91
PWM用定时器模拟即可,例如在定时中断里调用下面这个函数
void pwm1(void)
{
static unsigned char t;
t++;
if(t<占空比)PWM引脚置高;
else PWM引脚置低;
}

zjk 发表于 2013-5-3 17:25:27

{:lol:}飞线吧。。。

zjk 发表于 2013-5-3 17:26:30

PWM的话不建议用延时,定时比较好

w282529350 发表于 2013-5-4 10:21:12

定时器资源别浪费,模拟PWM就行

seeyou2013 发表于 2013-5-4 10:23:37

9楼模拟啊

李鸿鸿 发表于 2013-5-4 11:32:52

lcw_swust 发表于 2013-5-3 17:06 static/image/common/back.gif
http://www.amobbs.com/forum.php?mod=viewthread&tid=5039835&highlight=%E6%97%B6%E9%97%B4%E8%A7%A6%E5% ...

PCA改用定时器模式,再模拟,真的可以,而且是2个定时器,STC12C5A60S2就有4个定时器了,我怎么就没想到呢,谢谢你的分享

李鸿鸿 发表于 2013-5-4 11:40:13

seeyou2013 发表于 2013-5-4 10:23 static/image/common/back.gif
9楼模拟啊

void PCA_int0() interrupt 7 using 1
{
   if(CCF0==1)
   {
   CCF0=0;
   CCAP0L=value1;
   CCAP0H=value1>>8;
   value1+=THz;//频率
   if(cnt1++<=k1)//百分比
   {
             m2=1;
   }
   else
   {
             m2=0;
   }
   if(cnt1>1000)
      cnt1=0;
   }

   if(CCF1==1)
   {
   CCF1=0;
   CCAP1L=value2;
   CCAP1H=value2>>8;
   value2+=THz;
   if(cnt2++<=k2)
   {
             m3=1;
   }
   else
   {
             m3=0;
   }
   if(cnt2>1000)
      cnt2=0;
        }
}

玉洋子 发表于 2013-5-4 14:01:01

顶九楼!言简意赅{:victory:}

srygg 发表于 2013-5-4 14:57:59

请教一下楼主,用STC的单片机,编程序用仿真器吗?还是盲写啊?

x2816960 发表于 2013-5-4 15:04:47

用一个定时器,1ms进一次定时器中断。20ms一个周期,在定时器中断里设置占空比。

李鸿鸿 发表于 2013-5-4 16:33:08

srygg 发表于 2013-5-4 14:57 static/image/common/back.gif
请教一下楼主,用STC的单片机,编程序用仿真器吗?还是盲写啊?

我没用过仿真器,也不需要用的吧,计算一下就可以了

李鸿鸿 发表于 2013-5-4 16:35:35

x2816960 发表于 2013-5-4 15:04 static/image/common/back.gif
用一个定时器,1ms进一次定时器中断。20ms一个周期,在定时器中断里设置占空比。 ...

一个定时器可以控制2路PWM输出?精确吗?

kent 发表于 2013-5-4 17:36:21

该IC是51的核,用操作系统,一般是用Keil C TINY或FULL。如果没有用过该操作系统的话,我建议你别用。很多人都出现过莫名其妙的问题。我认为你的项目用普通的方法就可以了,并且频率不需要这么高,12MHz以下均可。PWM引脚不对可以飞线——正式定型前改硬件很正常。编程时不要用中断,否则太损耗系统资源了。无线不要用中断,否则你的系统很容易死机。用PCA设置成定时器模式,管理其它几个功能模块的切换。按以上方法设置,工作速度比操作系统快很多。

1148729990 发表于 2013-5-4 18:18:37

李鸿鸿 发表于 2013-5-4 16:35 static/image/common/back.gif
一个定时器可以控制2路PWM输出?精确吗?

可以满足你的要求{:shy:}

李鸿鸿 发表于 2013-5-4 23:25:00

kent 发表于 2013-5-4 17:36 static/image/common/back.gif
该IC是51的核,用操作系统,一般是用Keil C TINY或FULL。如果没有用过该操作系统的话,我建议你别用。很多 ...

试了一晚上,用实时操作系统还不太会,用普通的,效率更高,用12MHz的话,工作更稳定。谢谢你的精彩回答

李鸿鸿 发表于 2013-5-4 23:26:38

1148729990 发表于 2013-5-4 18:18 static/image/common/back.gif
可以满足你的要求

又可以减少一个定时器,想不到,谢谢你的建议

1148729990 发表于 2013-5-4 23:29:26

{:smile:}                  

sgzzour 发表于 2013-5-4 23:41:07

李鸿鸿 发表于 2013-5-4 16:35 static/image/common/back.gif
一个定时器可以控制2路PWM输出?精确吗?

没问题。绝对可以

huangyewei 发表于 2013-5-3 12:08:14

#include <STC_NEW_8051.h>
#define uchar unsigned char
#define uint unsigned int
#define N 2
#define Q 3
sbit dj1=P1^0;
sbit dj2=P1^1;
sbit dj3=P1^2;
sbit dj4=P1^3;
sbit dj5=P1^4;
uint count1=0,times=0;
uint count=0,a=0,b=0;
uchar code time[]={
30,40,N,N,N,N,N,N,N,N,
N,N,N,N,N,N,N,N,N,N,
N,N,N,N,N,N,N,N,N,N,
N,N,N,N,N,N,N,40,N,N,
N,N,N,N,N,N,N,N,N,N,

N,N,N,N,N,20,Q,Q,Q,Q,
Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,
Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,

30,Q,Q,Q,Q,Q,Q,Q,Q,Q,
Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,
Q,Q,Q,Q,Q
};
uchar code task[]=       //        {15,17,17,16,15};中间位置
{       
        {13,44,18,46,10},        //初始化   //1
        {13,44,18,46,50},        //拿树苗
        {13,43,19,46,50},
        {14,42,20,46,50},
        {15,42,20,46,50},                           //5
        {16,41,21,46,50},
        {17,41,22,46,50},
        {18,40,23,46,50},
        {19,39,23,46,50},
        {20,39,24,46,50},                           //10
        {21,38,24,46,50},
        {22,38,25,46,50},               
        {23,37,25,46,50},
        {24,37,26,46,50},
        {25,36,27,46,50},                           //15
        {26,36,27,46,50},
        {27,35,28,46,50},
        {28,35,28,46,50},
        {29,34,29,46,50},
        {30,34,30,42,50},        //举起           //20
        {31,34,30,46,50},
        {32,34,29,46,50},               
        {33,35,28,46,50},
        {34,35,28,46,50},
        {35,36,27,46,50},                           //25
        {36,36,27,46,50},
        {37,37,26,46,50},
        {38,37,25,46,50},
        {39,38,24,46,50},
        {40,38,23,42,50},                           //30
        {41,39,22,46,50},
        {42,39,21,45,50},               
        {43,40,20,45,50},
        {44,41,20,44,50},
        {45,42,19,44,50},                           //35
        {46,43,19,43,50},
        {47,43,18,43,50},
        {48,44,18,42,10},                //种树

        {47,44,19,42,10},
        {46,44,20,43,10},                           //40
        {45,44,21,43,10},               
        {44,45,22,44,10},
        {43,45,23,44,10},
        {42,45,23,45,10},
        {41,45,24,45,10},                           //45
        {40,45,24,46,10},
        {39,45,25,46,10},
        {38,45,26,45,10},               
        {37,45,27,45,10},
        {36,46,27,44,10},                          //50
        {35,46,28,44,10},
        {34,46,28,43,10},
        {33,46,29,43,10},
        {32,46,29,43,10},
        {31,46,30,42,10},                          //55
        {30,46,30,42,10},        //举起

        {30,46,30,50,30},//下
        {29,45,28,50,30},
        {28,44,26,49,30},
        {27,43,25,49,30},       //左下          //60
        {26,42,23,48,30},
        {25,41,20,47,30},
        {25,40,18,46,50},        //左
        {26,40,16,45,50},
        {26,39,14,44,50},                          //65
        {27,38,13,43,50},//左上
        {28,37,12,42,50},
        {29,36,11,41,50},
        {30,36,11,41,30},        //上
        {31,37,11,42,30},                          //70
        {32,37,12,42,30},
        {33,38,13,43,30},        // 右上
        {34,38,14,44,30},
        {35,39,16,45,30},
        {35,40,18,46,10},   //右
        {34,41,21,47,10},
        {34,42,23,48,10},
        {33,43,25,48,10},   //右下
        {32,44,26,49,11},
        {31,45,28,49,11},                          //80
//************************************************
        {30,35,19,29,10},//上                1
        {30,35,18,28,10},
        {31,36,18,27,10},
        {31,37,17,26,10},
        {32,38,17,25,10},
        {32,38,16,24,10},
        {33,39,16,23,10},       //右
        {33,40,16,23,10},
        {33,41,16,22,10},
        {32,42,16,21,10},//90
        {32,43,15,20,10},
        {31,44,15,19,10},
        {30,45,15,18,10},        // 下
        {29,44,15,19,10},
        {28,43,15,20,10},
        {28,42,16,21,10},
        {27,41,16,22,10},
        {27,40,16,23,10},
        {27,39,16,24,10},        //左
        {28,38,16,24,10},//100
        {28,38,17,25,10},
        {29,37,17,26,10},
        {29,36,18,27,10},
        {30,35,18,28,10},
        {30,35,19,29,10}//上          105
};       
void TimerInit()
{   
        TMOD=0x01;                       //设置定时器0为工作方式1                              
    TH0 = 0xFF;                       //定时器装初值
    TL0 = 0xd2;
        EA=1;                              //开总中断
        ET0=1;                                 //定时器0中断允许      
        TR0=1;                                  //启动定时器0
}                                                                       
void main(void)
{
        TimerInit();
        P1M0 = 0X1f;
        P1M1 = 0X00;
    while(1){}
}

void timer0(void) interrupt 1 using 0
{
    TH0=0xFF;
    TL0=0xD2; //定时器0重新装入数值          0.05ms中断               
        if (count==0)                                           dj1=1;
        if (count==task )                 dj1=0;
        if (count==40)                                dj2=1;               
        if (count==task+40)                dj2=0;       
        if (count==80)                                dj3=1;               
        if (count==task+80)                dj3=0;
        if (count==120)                                dj4=1;               
        if (count==task+120)        dj4=0;
        if (count==160)                                dj5=1;               
        if (count==task+160)        dj5=0;                                                       
        count++;   
        if(count==380)                {count=0;        count1++;}          //20ms到
        if(count1==time)       
        {
                count1=0;a++;
                if(a>79)
                {
                        if(b<2)        {a=56;b++;}
                          else{if(a>104){a=81;}}
                }                        
        }
}

huangyewei 发表于 2013-5-5 00:08:10

利用定时器和二维数组输出5路PWM控制5路舵机,测试OK,楼主如果看得懂这个程序的话输出两路PWM是完全没有问题的。

wugang_1213 发表于 2013-5-5 09:42:42

多任务,用调度器,论坛里有帖子的,搜搜看。{:lol:}

zhxzhx 发表于 2013-5-6 03:05:07

怎么会有7个任?你不能一个IO就用一个任务处理吧?

李鸿鸿 发表于 2013-5-6 12:37:56

huangyewei 发表于 2013-5-5 00:08 static/image/common/back.gif
利用定时器和二维数组输出5路PWM控制5路舵机,测试OK,楼主如果看得懂这个程序的话输出两路PWM是完全没有问 ...

上面的程序看得懂;我用一个PCA做定时器用,PWM输出的话还可以,但当加其它程序放while循环时,PWM输出隔一段时间就有一小点不稳定,还不知道是什么回事呢

李鸿鸿 发表于 2013-5-6 12:41:51

wugang_1213 发表于 2013-5-5 09:42 static/image/common/back.gif
多任务,用调度器,论坛里有帖子的,搜搜看。

我用过了,用多任务实时操纵系统,调度5个任务,搞了几天,但就是有许多问题,所以干脆不用,直接用普通方法

李鸿鸿 发表于 2013-5-6 12:44:50

zhxzhx 发表于 2013-5-6 03:05 static/image/common/back.gif
怎么会有7个任?你不能一个IO就用一个任务处理吧?

IO口基本用完,任务加起来总共有7个,2路PWM,2路检测,无线发射和接收,液晶显示,蜂鸣器,总共就7个任务了

zhxzhx 发表于 2013-5-10 19:08:56

李鸿鸿 发表于 2013-5-6 12:44 static/image/common/back.gif
IO口基本用完,任务加起来总共有7个,2路PWM,2路检测,无线发射和接收,液晶显示,蜂鸣器,总共就7个任 ...

如果你要软件模拟pwm,还是尽量不要用多任务系统,多任务在宏观上同时进行,微观上同步性很差。

李鸿鸿 发表于 2013-6-29 17:11:57

谢谢大家的关心,我的智能小车可以走了http://www.amobbs.com/thread-5540397-1-1.html
资料都在这个帖子里

XY19900220 发表于 2013-7-3 18:52:10

你这个功能太复杂了,要弄清他们之前的关系,方可; 可以移植rtos,进行任务调度.

李鸿鸿 发表于 2013-7-3 18:57:40

XY19900220 发表于 2013-7-3 18:52 static/image/common/back.gif
你这个功能太复杂了,要弄清他们之前的关系,方可; 可以移植rtos,进行任务调度. ...

我用过多线程操作系统了,就是那个《从单片机初学者到单片机工程师》的那个帖子的,其实这个也可以了

Zhuang0805 发表于 2013-7-3 22:23:28

用定时器模仿PWM输出,或者换MCU,STM8定时器有多个通道。
页: [1]
查看完整版本: 用STC12C5A60S2做的智能小车出现问题(PWM)