|
5黑幣
是利用ad/da控制電樞電流控制轉(zhuǎn)速附件有程序和proteus仿真。
因為是新手,第一次寫c程序。設(shè)計速度加上去后再減速發(fā)現(xiàn)不能達(dá)到要求,請各位幫幫忙。
單片機(jī)源程序如下:
#include <reg52.h>
#define digital P0 //DAC0832 數(shù)據(jù)管腳
#define leddat P1 //數(shù)碼管數(shù)據(jù)管腳
#define en 1 //電機(jī)一圈的脈沖數(shù) 根據(jù)電機(jī)實際參數(shù)設(shè)定
#define uint unsigned int
#define uchar unsigned char
#define ufloat unsigned float
sbit scl=P3^5;
sbit sda=P3^7;
sbit Y3 = P3^0; //數(shù)碼管段選腳定義
sbit Y2 = P3^1;
sbit Y1 = P3^2;
sbit Y0 = P3^3;
sbit Y7 = P2^0; //數(shù)碼管段選腳定義
sbit Y6 = P2^1;
sbit Y5 = P2^2;
sbit Y4 = P2^3;
sbit LSA = P2^4; //138譯碼器管腳定義
sbit LSB = P2^5;
sbit LSC = P2^6;
sbit LSG1 = P2^7;
char code Led_dat[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //共陰數(shù)碼管段碼 0123456789
long double speed=0;
long int count=0; //記錄脈沖數(shù)量
void Delay10us()
{
unsigned char a,b;
for(b=1;b>0;b--)
for(a=2;a>0;a--);
}
void delay() //延時幾微秒。延時函數(shù)在很多函數(shù)里都要用它。至少要大于4.7us
{;;} //當(dāng)你把這個函數(shù)寫在用它這個函數(shù)的前面就不用聲明了
void init() //初始化總線。將總線都拉高以釋放
{
scl=1;
delay(); //I2C總線使用時一般都要延時5us左右
sda=1;
delay();
}
void start() //啟始信號。 時鐘信號為高電平期間,數(shù)據(jù)總線產(chǎn)生下降沿。
{ //為什么要下降沿,且sda先要為1。因為先要保證數(shù)據(jù)線為空才能工作
sda=1; //先釋放數(shù)據(jù)總線。高電平釋放
delay();
scl=1;
delay();
sda=0;
delay();
}
void stop()
{
sda=0; //先要有工作狀態(tài)才能釋放,sda=0時在工作狀態(tài)
delay();
scl=1;
delay();
sda=1; //釋放數(shù)據(jù)總線
delay();
}
void respons() //應(yīng)答函數(shù)
{
uchar i=0;
scl=1; //每個字節(jié)發(fā)送完后的第九個時鐘信號的開始
delay();
while((sda==1)&&(i<255)) //此處i的定義使用了uchar.只要填一個小于255的就行
i++; //此處的sda是從機(jī)的
scl=0; //表示主器件默認(rèn)從器件已經(jīng)收到而不再等待。不再等待之后,時鐘的高電平過了就是低電平,所以scl=0
//此時第酒個時鐘信號結(jié)束
}
void writebyte(uchar d) //寫一字節(jié),每次左移一位
{
uchar i,temp;
temp=d;
for(i=0;i<8;i++)
{
temp=temp<<1;
scl=0; //數(shù)據(jù)傳輸期間要想sda可變,先把時鐘拉低。此處要給sda賦值
delay();
sda=CY; //CY為左移移入PSW寄存器中的的CY位。
delay();
scl=1; //sda有數(shù)據(jù)了。保持?jǐn)?shù)據(jù)穩(wěn)定
delay();
}
scl=0; //此處是寫數(shù)據(jù),是屬于數(shù)據(jù)傳輸過程中。只有在時鐘信號為低電平期間
delay(); //數(shù)據(jù)總線才可以變化。
sda=1; //所以要想釋放數(shù)據(jù)總線,就必須先把時鐘拉低
delay();
/*此處釋放總線寫在末尾是因為調(diào)用它時,前面有起始函數(shù)釋放了總線*/
}
uchar readbyte()
{
uchar i,k;
scl=0;
delay();
sda=1;
delay();
/*此處釋放總線放在前面是因為一般都是先寫后讀,保險起見,釋放一下總線*/
for(i=0;i<8;i++)
{
scl=1; //一個時鐘信號的開始
delay();
k=(k<<1)|sda; //實質(zhì)是把sda的數(shù)據(jù),最先傳來的放在最高位,依次往下排
scl=0; //一個時鐘信號結(jié)束
delay();
}
return k;
}
void write(uchar addr,uchar dat)
{
start(); //初始化
writebyte(0x90); //調(diào)用寫一字節(jié)函數(shù).PCF8591為1001。此處是給從機(jī)發(fā)送寫信號(最低位是0)
respons(); //調(diào)用應(yīng)答函數(shù)讓從機(jī)應(yīng)答
writebyte(addr); //寫入地址
respons(); //每寫一字節(jié)都要應(yīng)答
writebyte(dat);
respons();
stop();
}
uchar read(uchar addr)
{
uchar dat;
start();
writebyte(0x90); //從此處的發(fā)送地址和方向位0到從機(jī)
respons(); //此處的從機(jī)產(chǎn)生應(yīng)答。屬于“偽寫”。用于確定和哪臺機(jī)子通信
writebyte(addr);
respons();
start();
writebyte(0x91); //從此處開始,從機(jī)向主機(jī)寫數(shù)據(jù)。讀的方向位為1
respons();
dat=readbyte();
stop();
return dat; //讀得的數(shù)據(jù)要返回
}
void delay1(int i) //延時函數(shù)
{
while(i--);
}
void display(int x,int y) //數(shù)碼管操作函數(shù)
{
delay1(100);
leddat = ~0x00; //清屏消隱
Y0=0;Y1=1;Y2=1;Y3=1;Y4=1;Y5=1;Y6=1;Y7=1; //段選1
leddat = ~Led_dat[x%10]; //取余數(shù) 取出個位數(shù)
delay1(100);
leddat = ~0x00;
Y0=1;Y1=0;Y2=1;Y3=1;Y4=1;Y5=1;Y6=1;Y7=1; //段選2
leddat = ~Led_dat[x/10%10]; //取出十位數(shù)
delay1(100);
leddat = ~0x00;
Y0=1;Y1=1;Y2=0;Y3=1;Y4=1;Y5=1;Y6=1;Y7=1; //段選3
leddat = ~Led_dat[x/100%10]; //取出百位數(shù)
delay1(100);
leddat = ~0x00;
Y0=1;Y1=1;Y2=1;Y3=0;Y4=1;Y5=1;Y6=1;Y7=1; //段選4
leddat = ~Led_dat[x/1000]; //取出千位數(shù)
delay1(100);
leddat = ~0x00; //清屏消隱
Y0=1;Y1=1;Y2=1;Y3=1;Y4=0;Y5=1;Y6=1;Y7=1; //段選5
leddat = ~Led_dat[y%10]; //取余數(shù) 取出個位數(shù)
delay1(100);
leddat = ~0x00;
Y0=1;Y1=1;Y2=1;Y3=1;Y4=1;Y5=0;Y6=1;Y7=1; //段選6
leddat = ~Led_dat[y/10%10]; //取出十位數(shù)
delay1(100);
leddat = ~0x00;
Y0=1;Y1=1;Y2=1;Y3=1;Y4=1;Y5=1;Y6=0;Y7=1; //段選7
leddat = ~Led_dat[y/100%10]; //取出百位數(shù)
delay1(100);
leddat = ~0x00;
Y0=1;Y1=1;Y2=1;Y3=1;Y4=1;Y5=1;Y6=1;Y7=0; //段選8
leddat = ~Led_dat[y/1000]; //取出千位數(shù)
}
void timerInit()
{
TMOD=0x15; //模式設(shè)置,00000001
TR0=1; //打開計數(shù)器
ET0=1; //開計數(shù)器0中斷
TR1=1; //打開計數(shù)器
ET1=1; //開計數(shù)器0中斷
TH1=(65536-45872)/256; //50ms
TL1=(65536-45872)%256;
TH0=0;
TL0=0;
EA=1; //開總中斷
}
uint T0_read()
{
uchar tl,th1,th2;
uint val;
while(1)
{
th1=TH0;
tl=TL0;
th2=TH0;
if(th1==th2)
break;
}
val=th1*256+tl;
return val;
}
void main()
{
double dat = 0;
int dig=0;
int i;
int x_speed=150; //速度增量
LSA = 0; //138譯碼器 YC2輸出低
LSB = 1;
LSC = 0;
LSG1 = 1;
WR = 0; //打開dac0830轉(zhuǎn)換 WR輸出低
timerInit();
while(1)
{
dat=read(0x00);
dat = (dat*67)/255 + 17; //設(shè)定的每秒轉(zhuǎn)速 17~84r/s 對應(yīng) 1020~5040r/min
speed = count/en; //當(dāng)前速度
if(speed < dat) x_speed+=1; //如果實際速度小于設(shè)定速度 速度增量加
else x_speed-=1; //反之則減
if(x_speed > 255)x_speed = 255; //速度增量最大255 最小0
if(x_speed < 0) x_speed = 0;
digital =x_speed; //電機(jī)輸出速度為 設(shè)定速度加上速度增量
i=10;
while(i--)
{
i--;
display(speed*60,dat*60); //顯示當(dāng)前速度 每分鐘轉(zhuǎn)速
}
}
}
void timer_T1() interrupt 3 //定時器中斷
{
static int i = 0;
TH1=(65536-45872)/256; //50ms
TL1=(65536-45872)%256;
i++;
if(i>=20) //20*50=1000ms 定時1s
{
TR0=0; //關(guān)閉計數(shù)器 記錄脈沖數(shù)量
count=T0_read();
TH0=0;
TL0=0;
i=0; //脈沖清零 重新開始計數(shù)
TR0=1;
}
}
|
-
-
-
調(diào)速.zip
2020-1-1 10:24 上傳
點擊文件名下載附件
115.21 KB, 下載次數(shù): 6
|