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