這篇學習筆記雖然看起來很水,畢竟紅外避障和PWM在之前的學習筆記裏都寫過了,但這次確實是我耗時最久的一次作業。
用軟件實現PWM真是一個深淵巨坑…
首先是由於小車的方向函數的運作方式是切換運動狀態,而我們用PWM的目的是要使小車在執行主函數時的運動速度始終保持我們設定的值,因此我們在一個週期中讓電機停轉的時候就不能只是簡單的調用一個stop函數,而是要先將此刻小車的運動狀態記錄下來,以用來在下一個週期開始時使小車恢復原先的運動狀態。我剛開始想將這個用於記錄的函數寫進中斷程序裏以方便以後寫程序好直接移植,結果出現了各種各樣的邏輯錯誤…後來發現最簡單的方法就是在每次小車改變運動狀態後直接記錄,雖然代碼看起來臃腫了許多,但邏輯變得清晰了不少。
在解決了第一個問題後,信心滿滿的將我的程序燒錄到小車裏,然後我發現我的小車就像得了腦血栓似的,你永遠不知道他會在什麼時候將哪行命令執行多長時間,又會在什麼時候突然罷工…後來我發現(只是猜測)這是因爲你永遠不知道中斷程序會在你的主程序執行到哪一步時忽然跳出來,他有可能在你的方向函數執行到一半時突然執行中斷程序導致你的方向沒有順利改變,也可能在你的記錄函數記錄運動狀態之前突然中斷使記錄發生錯誤…總之就是非常噁心人。於是我乾脆直接在執行每個方向函數之前都重置一邊定時器,在使我的代碼又胖了一圈後終於解決了問題…
當然還有許多其他各種各樣的小問題,比如中斷程序導致Delay函數的延時參數形同虛設啦,因爲各種函數的邏輯衝突導致小車抽風啦,總之,歷經千辛萬苦,我終於是將這麼簡單的一個功能搞定了…突然感覺自己好菜啊…
下面是被我改到和我的身材一樣臃腫的代碼(包含方向函數的頭文件direction我就不往出列了)
#include <REGX52.H>
#include "direction.h"
#include "cd.h"
#define u8 unsigned char
#define u16 unsigned int
sbit BZL=P2^0 ;
sbit BZR=P2^1 ;
u8 iw=1;
u16 time_cnt=0;
u16 freq=100; //PWM輸出頻率
u16 duty_cycle=20; //佔空比
void Timer0Init(void)
{
TMOD &= 0xF0;
TMOD = 0x01;
TL0 = 0xA4; //定時器設定爲0.1ms
TH0 = 0xFF;
TF0 = 0;
TR0 = 1;
ET0 = 1;
EA = 1;
}
void main()
{
forward();
iw=dd(); //dd函數的功能是將當前運動狀態的編號return
Timer0Init();
while(1)
{
if(BZR==0)
{
Timer0Init();
back();
iw=dd();
Delay(100);
Timer0Init();
left();
iw=dd();
Delay(160);
Timer0Init();
forward();
iw=dd();
}
if(BZL==0)
{
Timer0Init();
back();
iw=dd();
Delay(100);
Timer0Init();
right();
iw=dd();
Delay(160);
Timer0Init();
forward();
iw=dd();
}
}
}
void timer0 () interrupt 1
{
TR0=0;
TL0 = 0xA4;
TH0 = 0xFF;
time_cnt++;
if(time_cnt>=(10000/freq)) time_cnt=0;
else if(time_cnt<=(duty_cycle/((10000/freq)/100)))
{
cd(iw); //cd函數功能爲按照輸入的編號改變運動狀態
}
else
{
stop();
}
TR0=1;
}
頭文件
cd.c
#include <REGX52.H>
#include "direction.h"
sbit L1=P0^0;
sbit L2=P0^1;
sbit R1=P0^2;
sbit R2=P0^3;
u8 dd ()
{
u8 s;
if(L1==0&&L2==0&&R1==0&&R2==0) s=0;
if(L1==1&&L2==0&&R1==1&&R2==0) s=1;
if(L1==0&&L2==1&&R1==0&&R2==1) s=2;
if(L1==0&&L2==0&&R1==1&&R2==0) s=3;
if(L1==1&&L2==0&&R1==0&&R2==0) s=4;
return s;
}
void cd (u8 e)
{
if(e==0) stop();
if(e==1) forward();
if(e==2) back();
if(e==3) left();
if(e==4) right();
}
cd.h
#ifndef __cd_H__
#define __cd_H__
u8 dd ();
void cd (u8 e);
#endif