欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136
標題:
單片機控制4電機循環測試(數碼管顯示)構思與實現源代碼
[打印本頁]
作者:
miaoxiaobaiqaq
時間:
2019-4-12 23:56
標題:
單片機控制4電機循環測試(數碼管顯示)構思與實現源代碼
實驗構思:
一, 兩位共陰數碼管4個,要求顯示范圍0.0~9.9 分別對應4個電機運行時間; 開機無顯示,
當電機運行時,對應的數碼管從0開始計時,設定的時間到電機停止運行,數碼管保持停止時間上.當下個電機運行時熄滅.
二 按鍵加減范圍1~99 ,按設置鍵3秒進入電機1時間設置 ,(K_SET) 進入設置后,上次設置的數字閃爍, 用 K_UP和K_DN進行數字加減; 步進1,相當于時間0.1秒, 步數100個(0~99);進入設置后,再按設置鍵,每按一次,進行電機1,2,3,4,1.....循環,同時對應的數碼管閃爍,分別顯示AA,BB,CC,DD來區分,按下設置鍵,或者設置完成后3秒無任何按鍵操作;保存當前數據并退出設置狀態. ,在設置的時候不得影響程序的正常運行,設置保存后,程序立即運行新設置的數據.
P0 P0 P0 P0
P1^1 P1^0 P1^3 P1^2 P1^5 P1^4 P1^7 P1^6
數碼顯示1 數碼顯示2 數碼顯示3 數碼顯示4
開始----------->電機1-------------->電機2---------->電機3-------------電機4-------------->擋桿
PIN_POW PIN_DJA PIN_DJB PIN_DJC PIN_DJD PIN_STOP
P2^2 P2^3 P2^4 P2^5 P2^6 P2^7
控制1 控制2 控制3
PA1 P3^0 PA2 P3^1 PA3^2
K_POW按一次開機,再按一次停機. K_POW=P3^4, K_SET=P3^5, K_UP=P3^6, K_DN=P3^7,
控制觸發是低電平有效 輸出為低電平 單片機STC89C52 程序C,不要匯編等.
工作過程:
開始(PIN_POW=0,其他=1),等待控制1觸發,
控制1觸發 (PIN_POW=1,PIN_STOP=0, PIN_DJA =0)
電機1運轉時間到,PIN_DJA =1,等待控制2觸發.
控制2觸發.PIN_DJB =0,
電機2運轉時間到 PIN_DJB =1,PIN_DJC =0,電機3接著運行
電機3運轉時間到 PIN_DJC =1,PIN_DJD =0,電機4接著運行
電機4運轉時間到 PIN_DJD =1,等待控制3觸發.
控制3觸發.PIN_STOP=1,PIN_POW=0,.
整個過程無限循環,只有有開關機鍵控制;
按關機鍵后,等運行到PIN_POW=0時關機,不得在工作過程中途停機.
要求主程序和子程序分類;建立單獨的.h文件.此設計中需要設置的數據保存,斷電重新開機運行的是上次修改的參數.不得每次開機重新設定.
腳位功能在程序中直接定義,除數碼管P0口外,其他單個腳位不得使用代碼代替;
以上是題目,貼出全部單片機代碼
main.c
#include<STC15F2K60S2.H>
#include"delay.h"
#include"dj.h"
#include"key.h"
#include "eeprom.h"
uint time_DJA=3000;
uint time_DJB=3000;
uint time_DJC=3000;
uint time_DJD=3000;
extern bit flag_DJA1;
extern bit flag_DJB1;
extern bit flag_DJC1;
extern bit flag_DJD1;
extern bit flag_kaiguan;
sbit PA1=P2^0;
sbit PA2=P3^6;
sbit PA3=P3^7;
void main()
{
Init_Timer0();
PA1=1; //測試的時候用的
PA2=1; //測試的時候用的
PA3=1; //測試的時候用的
/*初始值從EEPROM 中讀取*/
time_DJA=iap_READ(iap_ADDRESS)*1000+iap_READ(iap_ADDRESS+1)*100+iap_READ(iap_ADDRESS+2)*10+iap_READ(iap_ADDRESS+3);
time_DJB=iap_READ(iap_ADDRESS+4)*1000+iap_READ(iap_ADDRESS+5)*100+iap_READ(iap_ADDRESS+6)*10+iap_READ(iap_ADDRESS+7);
time_DJC=iap_READ(iap_ADDRESS+8)*1000+iap_READ(iap_ADDRESS+9)*100+iap_READ(iap_ADDRESS+10)*10+iap_READ(iap_ADDRESS+11);
time_DJD=iap_READ(iap_ADDRESS+12)*1000+iap_READ(iap_ADDRESS+13)*100+iap_READ(iap_ADDRESS+14)*10+iap_READ(iap_ADDRESS+15);
while(1)
{
Key(); // 檢測開關是否按下,開關打開,開始執行下面的代碼
if(flag_kaiguan==1)
{
PIN_STOP=1; //停止指示燈
PIN_POW=0; //開始指示燈
delay_ms(50);//延時程序時間定義50ms,
if(PA1==1) //PA1觸發來到執行下面的代碼,相當于開門
{
PIN_POW=1;
PIN_STOP=0;
DJA(); //電機1開始執行
while(flag_DJA1==0)Key(); //等待電機1執行完畢
// delay_ms(1000); //測試的時候用的,假設1秒后觸發信號2來到了
while(PA2==0); //等待觸發信號2來
if(PA2==1)
{
DJB(); //電機B開始執行
while(flag_DJB1==0)Key(); //等待電機B執行結束
DJC(); //同理
while(flag_DJC1==0)Key();
DJD();
while(flag_DJD1==0)Key();
// delay_ms(1000); //測試的時候用的假設1秒后觸發信號3來到
while(PA3==0);
if(PA3==1)
{
PIN_STOP=1;
PIN_POW=0;
// PA1=0;
}
}
}
}
else TR0=0;P0=0X00; //開關關閉的時候把定時器關閉,數碼管再清空
}
///*下面的代碼可以用來第一次向EEPROM中寫入數據,以后都不會用到所以注釋掉*/
// iap_ERASE(iap_ADDRESS);
// iap_PROGRAM(iap_ADDRESS,3000/1000);
// iap_PROGRAM(iap_ADDRESS+1,3000/100%10);
// iap_PROGRAM(iap_ADDRESS+2,3000/10%10);
// iap_PROGRAM(iap_ADDRESS+3,3000%10);
//
// iap_PROGRAM(iap_ADDRESS+4,3000/1000);
// iap_PROGRAM(iap_ADDRESS+5,3000/100%10);
// iap_PROGRAM(iap_ADDRESS+6,3000/10%10);
// iap_PROGRAM(iap_ADDRESS+7,3000%10);
//
// iap_PROGRAM(iap_ADDRESS+8,3000/1000);
// iap_PROGRAM(iap_ADDRESS+9,3000/100%10);
// iap_PROGRAM(iap_ADDRESS+10,3000/10%10);
// iap_PROGRAM(iap_ADDRESS+11,3000%10);
//
// iap_PROGRAM(iap_ADDRESS+12,3000/1000);
// iap_PROGRAM(iap_ADDRESS+13,3000/100%10);
// iap_PROGRAM(iap_ADDRESS+14,3000/10%10);
// iap_PROGRAM(iap_ADDRESS+15,3000%10);
// while(1);
}
key.c
#include"key.h"
extern uint time_DJA;
extern uint time_DJB;
extern uint time_DJC;
extern uint time_DJD;
bit flag_key1=0; //設置鍵被按下三秒
bit flag_anjian=0; // 用于標記有按鍵按下,三秒無按鍵按下則退出設置界面
bit flag_kaiguan=0; //開關鍵1是開機,0是關機
uint key_num=1;
void Key()
{
if(K_SET ==0 && flag_key1==0) //檢查P3.7端口是否為低電平,即檢測S17是否被按下
{
delay_ms(2000); //再次檢測S17是否被按下
if(K_SET ==0)
{
while(K_SET == 0); //等待按鍵釋放
flag_key1=1;
}
}
if(flag_key1==1)
{
if(K_SET == 0) //檢查P3.7端口是否為低電平,即檢測S17是否被按下
{ //延時一定時間,去抖
delay_ms(10); //再次檢測S17是否被按下
if(K_SET == 0)
{
while(K_SET == 0); //等待按鍵釋放
key_num++;
flag_anjian=1;
if(key_num==5)
{
key_num=1;
}
}
}
}
if(flag_key1==1)
{
if(K_UP == 0) //檢查P3.7端口是否為低電平,即檢測S17是否被按下
{ //延時一定時間,去抖
delay_ms(10); //再次檢測S17是否被按下
if(K_UP == 0)
{
while(K_UP == 0); //等待按鍵釋放
flag_anjian=1;
switch(key_num)
{
case 1:
time_DJA+=100;
break;
case 2:
time_DJB+=100;
break;
case 3:
time_DJC+=100;
break;
case 4:
time_DJD+=100;
break;
}
}
}
if(K_DN == 0) //檢查P3.7端口是否為低電平,即檢測S17是否被按下
{ //延時一定時間,去抖
delay_ms(10); //再次檢測S17是否被按下
if(K_DN == 0)
{
while(K_DN == 0); //等待按鍵釋放
flag_anjian=1;
switch(key_num)
{
case 1:
time_DJA-=100;
break;
case 2:
time_DJB-=100;
break;
case 3:
time_DJC-=100;
break;
case 4:
time_DJD-=100;
break;
}
}
}
}
/*開關按鍵代碼*/
if(K_POW ==0 ) //檢查P3.7端口是否為低電平,即檢測S17是否被按下
{
delay_ms(10); //再次檢測S17是否被按下
if(K_POW ==0)
{
while(K_POW == 0); //等待按鍵釋放
flag_kaiguan=~flag_kaiguan;
}
}
}
delay.c
#include"delay.h"
/*==========================================================
函數名稱:void delayms(void)
形 參:無
返回值 :無
功能描述:1ms延時
時 間:2015-11-19
使 用:delayms();
==========================================================*/
void delayms(void) //@11.0592MHz
{
unsigned char i,j;
_nop_();
_nop_();
_nop_();
i = 11;
j = 190;
do
{
while (--j);
}
while (--i);
}
void delay_ms(unsigned int time)
{
unsigned int i;
for(i=0;i<time;i++)
delayms();
}
dj.c
#include"dj.h"
#include"key.h"
#include "eeprom.h"
extern uint key_num;
extern bit flag_key1;
extern uint key_num;
extern bit flag_anjian;
extern uint time_DJA;
extern uint time_DJB;
extern uint time_DJC;
extern uint time_DJD;
bit flag_DJA=0; //定時器運行電機A的代碼
bit flag_DJA1=0; //電機進入一次DJA()后主模塊就不第二次進去了
bit flag_DJB=0; //定時器運行電機B的代碼
bit flag_DJB1=0; //電機進入一次DJB()后主模塊就不第二次進去了
bit flag_DJC=0; //定時器運行電機C的代碼
bit flag_DJC1=0; //電機進入一次DJC()后主模塊就不第二次進去了
bit flag_DJD=0; //定時器運行電機D的代碼
bit flag_DJD1=0; //電機進入一次DJD()后主模塊就不第二次進去了
uint num=0;
uint num1=0;
uint num2=0; //用于在設置模式定時三秒,沒有操作則退出設置模式
uchar SMG_N[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; // 共陰極數碼管
uchar shu_1,shu_2,shu_3,shu_4,shu_5,shu_6,shu_7,shu_8;
void DJA()
{
TR0=1;// 定時器0打開
num=0;
PIN_DJA=0;
flag_DJD=0;
flag_DJD1=0;
flag_DJA=1;
}
void DJB()
{
TR0=0;// 定時器0關閉 //還原定時器0
TH0=(65536-45872)/256; //11.0592 晶振定時50ms還原定時器0
TL0=(65536-45872)%256; //還原定時器0
num=0; //還原定時器0
flag_DJA=0; //還原A的標志位
flag_DJA1=0; //還原A的標志位
PIN_DJB=0;
flag_DJB=1;
TR0=1;
}
void DJC()
{
TR0=0;// 定時器0關閉
TH0=(65536-45872)/256; //11.0592 晶振定時50ms
TL0=(65536-45872)%256;
num=0;
flag_DJB=0; //還原B的標志位
flag_DJB1=0; //還原B的標志位
PIN_DJC=0;
flag_DJC=1;
TR0=1;
}
void DJD()
{
TR0=0;// 定時器0關閉
TH0=(65536-45872)/256; //11.0592 晶振定時50ms
TL0=(65536-45872)%256;
num=0;
flag_DJC=0; //還原C的標志位
flag_DJC1=0; //還原C的標志位
PIN_DJD=0;
flag_DJD=1;
TR0=1;
}
void time0() interrupt 1
{
TH0=(65536-9216)/256; //11.0592 晶振定時50ms
TL0=(65536-9216)%256;
num++;num1++; //num1控制數碼管顯示num控制電機什么時候停止
/*電機A的代碼******************************************************************/
if(flag_DJA==1)
{
if(num>=(time_DJA/10)) //time_DJA是電機A轉動的時間,單位為ms
{
PIN_DJA=1;
flag_DJA1=1;
num=0;
}
if(PIN_DJA==0) //如果電機在運行則說明數碼管數子還在跳動
{
shu_1=(num/10)/10;
shu_2=(num/10)%10;
}
else
{
shu_1=(time_DJA/100)/10;
shu_2=(time_DJA/100)%10;
}
if(num1==1 && flag_key1==0)
{
P0=0X00;
P1=0xfe;
P0=SMG_N[shu_1]+128;
}
if(num1==2 && flag_key1==0 )
{
num1=0;
P0=0X00;
P1=0xfd;
P0=SMG_N[shu_2];
}
}
/******************************************************************************/
/*********************************************************************************/
/*d電機B的代碼 *******************************************************************/
if(flag_DJB==1)
{
if(num>=(time_DJB/10)) //time_DJA是電機A轉動的時間,單位為ms
{
PIN_DJB=1;
flag_DJB1=1;
num=0;
}
if(PIN_DJB==0) //如果電機在運行則說明數碼管數子還在跳動
{
shu_3=(num/10)/10;
shu_4=(num/10)%10;
}
else
{
shu_1=(time_DJB/100)/10;
shu_2=(time_DJB/100)%10;
}
if(num1==1 && flag_key1==0 )
{
P0=0X00;
P1=0xfb;
P0=SMG_N[shu_3]+128;
}
if(num1==2 && flag_key1==0 )
{
num1=0;
P0=0X00;
P1=0xf7;
P0=SMG_N[shu_4];
}
}
/****************************************************************************/
/*d電機C的代碼 *******************************************************************/
if(flag_DJC==1)
{
if(num>=(time_DJC/10)) //time_DJA是電機A轉動的時間,單位為ms
{
PIN_DJC=1;
flag_DJC1=1;
num=0;
}
if(PIN_DJC==0) //如果電機在運行則說明數碼管數子還在跳動
{
shu_5=(num/10)/10;
shu_6=(num/10)%10;
}
else
{
shu_5=(time_DJC/100)/10;
shu_6=(time_DJC/100)%10;
}
if(num1==1 && flag_key1==0 )
{
P0=0X00;
P1=0xef;
P0=SMG_N[shu_5]+128;
}
if(num1==2 && flag_key1==0 )
{
num1=0;
P0=0X00;
P1=0xdf;
P0=SMG_N[shu_6];
}
}
/****************************************************************************/
/*d電機D的代碼 *******************************************************************/
if(flag_DJD==1)
{
if(num>=(time_DJD/10)) //time_DJA是電機A轉動的時間,單位為ms
{
PIN_DJD=1;
flag_DJD1=1;
num=0;
}
if(PIN_DJD==0) //如果電機在運行則說明數碼管數子還在跳動
{
shu_7=(num/10)/10;
shu_8=(num/10)%10;
}
else
{
shu_7=(time_DJD/100)/10;
shu_8=(time_DJD/100)%10;
}
if(num1==1 && flag_key1==0 )
{
P0=0X00;
P1=0xBf;
P0=SMG_N[shu_7]+128;
}
if(num1==2 && flag_key1==0 )
{
num1=0;
P0=0X00;
P1=0x7f;
P0=SMG_N[shu_8];
}
}
/****************************************************************************/
/*按下設置鍵后數碼管顯示的代碼*/
if(flag_key1==1)
{
switch(key_num)
{
case 1:
if(num1==1)
{
P0=0X00;
P1=0xfe;
P0=SMG_N[(time_DJA/100)/10]+128;
}
if(num1==2)
{
num1=0;
P0=0X00;
P1=0xfd;
P0=SMG_N[(time_DJA/100)%10];
}break;
case 2:
if(num1==1)
{
P0=0X00;
P1=0xfb;
P0=SMG_N[(time_DJB/100)/10]+128;
}
if(num1==2)
{
num1=0;
P0=0X00;
P1=0xf7;
P0=SMG_N[(time_DJB/100)%10];
}break;
case 3:
if(num1==1)
{
P0=0X00;
P1=0xef;
P0=SMG_N[(time_DJC/100)/10]+128;
}
if(num1==2)
{
num1=0;
P0=0X00;
P1=0xdf;
P0=SMG_N[(time_DJC/100)%10];
}break;
case 4:
if(num1==1)
{
P0=0X00;
P1=0xbf;
P0=SMG_N[(time_DJD/100)/10]+128;
}
if(num1==2)
{
num1=0;
P0=0X00;
P1=0x7f;
P0=SMG_N[(time_DJD/100)%10];
}break;
}
}
/* 進入設置后三秒沒有操作自動退出并且把數據保存到EEPROM*/
if(flag_key1==1)
{
num2++;
if(num2==300)
{
flag_key1=0;
iap_ERASE(iap_ADDRESS);
iap_PROGRAM(iap_ADDRESS,time_DJA/1000);
iap_PROGRAM(iap_ADDRESS+1,time_DJA/100%10);
iap_PROGRAM(iap_ADDRESS+2,time_DJA/10%10);
iap_PROGRAM(iap_ADDRESS+3,time_DJA%10);
iap_PROGRAM(iap_ADDRESS+4,time_DJB/1000);
iap_PROGRAM(iap_ADDRESS+5,time_DJB/100%10);
iap_PROGRAM(iap_ADDRESS+6,time_DJB/10%10);
iap_PROGRAM(iap_ADDRESS+7,time_DJB%10);
iap_PROGRAM(iap_ADDRESS+8,time_DJC/1000);
iap_PROGRAM(iap_ADDRESS+9,time_DJC/100%10);
iap_PROGRAM(iap_ADDRESS+10,time_DJC/10%10);
iap_PROGRAM(iap_ADDRESS+11,time_DJC%10);
iap_PROGRAM(iap_ADDRESS+12,time_DJD/1000);
iap_PROGRAM(iap_ADDRESS+13,time_DJD/100%10);
iap_PROGRAM(iap_ADDRESS+14,time_DJD/10%10);
iap_PROGRAM(iap_ADDRESS+15,time_DJD%10);
}
if(flag_anjian==1)
{
flag_anjian=0;
num2=0;
}
}
}
void Init_Timer0(void)
{
AUXR=0X00; //定時器0 定時器 1工作在12分頻 即1T
TMOD=0x11; //定時器0 和定時器1 不可自動重裝載模式
TH0=(65536-9216)/256; //11.0592 晶振定時50ms
TL0=(65536-9216)%256;
TL1 = (65536-46080)/256; // 11.0592 晶振定時20ms
TH1 = (65536-46080)%256;
TR0=0; //定時器0關閉
TR1 = 0; //定時器1關閉
ET0=1; //允許定時器0中斷
ET1=1; //允許定時器1中斷
EA=1; //開啟總中斷
}
eeprom.c
#include "eeprom.h"
//使硬件或軟件操作停止
void iap_IDLE()
{
IAP_CONTR=0; //禁止IAP讀寫擦除
IAP_CMD=0; //等待
IAP_TRIG=0; //命令未觸發
IAP_ADDRH=0x80; //高位數據地址
IAP_ADDRL=0; //低位
}
//從數據里面讀取數據
uchar iap_READ(uint addr)
{ uchar datas;
IAP_CONTR=IAP_EN; //控制允許位
IAP_CMD=CMD_READ; //寫入讀命令
IAP_ADDRL=addr; //自定義地址
IAP_ADDRH=addr>>8;
IAP_TRIG=0x5a; //命令有效
IAP_TRIG=0xa5;
_nop_();
datas=IAP_DATA;
iap_IDLE();
return datas; //返回讀出的數據
}
//寫一個比特ISP寫到某個地方
void iap_PROGRAM(uint addr,uchar datas)
{
IAP_CONTR=IAP_EN;
IAP_CMD=CMD_PROGRAM;
IAP_ADDRL=addr;
IAP_ADDRH=addr>>8;
IAP_DATA=datas;
IAP_TRIG=0x5a;
IAP_TRIG=0xa5;
_nop_();
iap_IDLE();
}
//擦掉某個區域
void iap_ERASE(uint addr)
{
IAP_CONTR=IAP_EN;
IAP_CMD=CMD_ERASE;
IAP_ADDRL=addr;
IAP_ADDRH=addr>>8;
IAP_TRIG=0x5a;
IAP_TRIG=0xa5;
_nop_();
iap_IDLE();
}
復制代碼
作者:
miaoxiaobaiqaq
時間:
2019-4-12 23:58
新手,有更好的實現方式可以一起交流,一起進步
歡迎光臨 (http://www.raoushi.com/bbs/)
Powered by Discuz! X3.1