本文目錄一覽:
彙編語言編程 秒錶程序
直接發給你把
PROCESSOR 16C74
INCLUDE “P16C74B.INC “
SEC EQU 0X23 ;
MSEC EQU 0x24
TEMP1 EQU 0X22
FLAG2 EQU 0X28
ORG 0x00
GOTO START
ORG 0x04 ; 設定中斷向量
BCF STATUS,RP0
BTFSC INTCON,T0IF ; 判斷TIER0中斷標誌位是否被設置
GOTO TMR0_ISR ; 若是,則去執行TIMER0中斷子程序
RETFIE
START:
CALL PIC_INIT ;去設置埠、TIMER0工作模式
BSF INTCON,GIE
BSF INTCON,T0IE
MAIN_LOOP:
;程序的主體是個無限循環
BTFSC FLAG2,7
CALL DISPLAY
GOTO MAIN_LOOP
PIC_INIT:
CLRF INTCON
BCF INTCON,T0IE
BSF STATUS,RP0
MOVLW B’00000000′ ;B』XXXXXXXX』表示單引號中的數是二
MOVWF TRISB
MOVLW B’00000000′
MOVWF TRISC
BCF STATUS,RP0
MOVLW B’11000000′ ;B』XXXXXXXX』表示單引號中的數是二
MOVWF PORTB
MOVLW B’11000000′
MOVWF PORTC
BSF STATUS,RP0
MOVLW B’11000100′
MOVWF OPTION_REG ; 對TIMER0工作模式進行設置,32分頻
BCF STATUS,RP0
MOVLW 0X06
MOVWF TMR0
CLRF SEC
CLRF MSEC
CLRF TEMP1
CLRF FLAG2
RETURN
TMR0_ISR:
CLRWDT
BSF FLAG2,7
BCF INTCON,T0IF
MOVLW 0X06
MOVWF TMR0
CLRWDT
INCF TEMP1,1
MOVF TEMP1,0
SUBLW .125 ;125-TEMP
BTFSS STATUS,2
RETFIE
CLRWDT
CLRF TEMP1
INCF MSEC,1
RETFIE
DISPLAY:
MOVF MSEC,0
SUBLW .10
BTFSS STATUS,2
GOTO NEXT_1
CLRWDT
CLRF MSEC
INCF SEC,1
MOVF SEC,0
SUBLW .6
BTFSS STATUS,2
GOTO NEXT_1
CLRF SEC
NEXT_1:
CLRWDT
MOVF MSEC,W
CALL CHAR_CODE
MOVWF PORTC
MOVF SEC,W
CALL CHAR_CODE
MOVWF PORTB
BCF FLAG2,7
RETURN
CHAR_CODE:
ADDWF PCL,1 ;PCL+=W
RETLW B’11000000′ ; Code for 0
RETLW B’11111001′ ; Code for 1
RETLW B’10100100′ ; Code for 2
RETLW B’10110000′ ; Code for 3
RETLW B’10011001′ ; Code for 4
RETLW B’10010010′ ; Code for 5
RETLW B’10000010′ ; Code for 6
RETLW B’11111000′ ; Code for 7
RETLW B’10000000′ ; Code for 8
RETLW B’10010000′ ; Code for 9
END
創建一個C語言程序顯示出y=1+2+3++。。。10 的計算結果
我原來找到的文章
在工業生產控制系統中,有許多需要定時完成的操作,如:定時顯示當前時間,定時刷新屏幕上的進度條,上位機定時向下位機發送命令和傳送數據等。特別是在對控制性能要求較高的控制系統和數據採集系統中,就更需要精確定時操作。
眾所周知,Windows是基於消息機制的系統,任何事件的執行都是通過發送和接收消息來完成的。這樣就帶來了一些問題,如一旦計算機的CPU被某個進程佔用,或系統資源緊張時,發送到消息隊列中的消息就暫時被掛起,得不到實時處理。因此,不能簡單地通過Windows消息引發一個對定時要求嚴格的事件。另外,由於在Windows中已經封裝了計算機底層硬體的訪問,所以,要想通過直接利用訪問硬體來完成精確定時,也比較困難。所以在實際應用時,應針對具體定時精度的要求,採取相適應的定時方法。
VC++的時間操作函數
VC++ 中提供了很多關於時間操作的函數,利用它們控制程序能夠精確地完成定時和計時操作。VC++中的WM_TIMER消息映射能進行簡單的時間控制。首先調用函數SetTimer()設置定時間隔,如SetTimer(0,200,NULL)即為設置200ms的時間間隔。然後在應用程序中增加定時響應函數OnTimer(),並在該函數中添加響應的處理語句,用來完成到達定時時間的操作。這種定時方法非常簡單,但其定時功能如同Sleep()函數的延時功能一樣,精度非常低,只可以用來實現諸如點陣圖的動態顯示等對定時精度要求不高的情況。
在精度要求較高的情況下,如要求誤差不大於1ms時,可以利用GetTickCount()函數。該函數的返回值是DWORD型,表示以ms為單位的計算機啟動後經歷的時間間隔。下列的代碼可以實現50ms的精確定時,其誤差小於1ms。
// 起始值和中止值
DWORD dwStart, dwStop ;
dwStop = GetTickCount();
while(TRUE)
{
// 上一次的中止值變成新的起始值
dwStart = dwStop ;
// 此處添加相應控制語句
do
{
dwStop = GetTickCount() ;
}while(dwStop - 50 dwStart) ;
}
對於精確度要求更高的定時操作,則應該使用QueryPerformanceFrequency()和QueryPerformanceCount
er()函數。這兩個函數是VC++提供的僅供Windows 95及其後續版本使用的精確時間函數,並要求計算機從硬體上支持精確定時器。QueryPerformanceFrequency()函數和QueryPerformanceCounter()函數的原型如下:
BOOL QueryPerformanceFrequency
(LARGE_INTEGER *lpFrequency);
BOOL QueryPerformanceCounter
(LARGE_INTEGER *lpCount);
數據類型LARGE_INTEGER既可以是一個8位元組長的整型數,也可以是兩個4位元組長的整型數的聯合結構,其具體用法根據編譯器是否支持64位而定。該類型的定義如下:
typedef union _LARGE_INTEGER
{
struct
{
// 4位元組整型數
DWORD LowPart ;
// 4位元組整型數
LONG HighPart ;
};
// 8位元組整型數
LONGLONG QuadPart ;
} LARGE_INTEGER ;
在進行定時之前,先調用QueryPerformanceFrequency()函數獲得機器內部定時器的時鐘頻率,然後在需要嚴格定時的事件發生之前和發生之後分別調用QueryPerformanceCounter()函數,利用兩次獲得的計數之差及時鐘頻率,計算出事件經歷的精確時間。下面的程序用來測試函數Sleep(100)的精確持續時間:
LARGE_INTEGER litmp;
LONGLONG QPart1,QPart2;
double dfMinus, dfFreq, dfTim;
QueryPerformanceFrequency(&litmp);
// 獲得計數器的時鐘頻率
dfFreq = (double)litmp.QuadPart;
QueryPerformanceCounter(&litmp);
// 獲得初始值
QPart1 = litmp.QuadPart;
Sleep(100);
QueryPerformanceCounter(&litmp);
// 獲得中止值
QPart2 = litmp.QuadPart;
dfMinus = (double)(QPart2 - QPart1);
// 獲得對應的時間值
dfTim = dfMinus / dfFreq;
由於Sleep()函數自身的誤差,上述程序每次執行的結果都會有微小誤差。
使用多媒體定時器
微軟公司在其多媒體Windows中提供了精確定時器的底層API支持。利用多媒體定時器可以很精確地讀出系統的當前時間,並且能在非常精確的時間間隔內完成一個事件、函數或過程的調用。利用多媒體定時器的基本功能,可以通過兩種方法實現精確定時。
1.使用timeGetTime()函數
該函數定時精度為ms級,返回從Windows啟動開始所經過的時間。由於使用該函數是通過查詢的方式進行定時控制的,所以,應該建立定時循環來進行定時事件的控制。
2. 使用timeSetEvent()函數
利用該函數可以實現周期性的函數調用。函數的參數說明如下:
uDelay:延遲時間;
uResolution:時間精度,在Windows中預設值為1ms;
lpFunction:回調函數,為用戶自定義函數,定時調用;
dwUser:用戶參數;
uFlags:標誌參數;
TIME_ONESHOT:執行一次;
TIME_PERIODIC:周期性執行。
具體應用時,可以通過調用timeSetEvent()函數,將需要周期性執行的任務定義在lpFunction回調函數中(如:定時採樣、控制等),從而完成所需處理的事件。需要注意的是:任務處理的時間不能大於周期間隔時間。另外,在定時器使用完畢後,應及時調用timeKillEvent()將之釋放。
下面這段代碼的主要功能是設置兩個時鐘定時器,一個間隔是1ms,一個間隔是2s。每執行一次,把當前系統時鐘值輸入文件「cure.out」中,以比較該定時器的精確度。
//定義1ms和2s時鐘間隔,以ms為單位
# define ONE_MILLI_SECOND 1
# define TWO_SECOND 2000
//定義時鐘解析度,以ms為單位
# define TIMER_ACCURACY 1
//定義時間間隔
UINT wTimerRes_1ms,wTimerRes_2s;
//定義解析度
UINT wAccuracy;
//定義定時器句柄
UINT TimerID_1ms,TimerID_2s;
//打開輸出文件「cure.out」
CCureApp::CCureApp():fout(「cure.out」, ios::out)
{
// 給時間間隔變數賦值
wTimerRes_1ms = ONE_MILLI_SECOND;
wTimerRes_2s = TWO_SECOND;
TIMECAPS tc;
//利用函數timeGetDevCaps取出系統解析度的取值範圍,如果無錯則繼續
if(timeGetDevCaps(&tc,sizeof(TIMECAPS))==TIMERR_NOERROR)
{
//解析度的值不能超出系統的取值範圍
wAccuracy=min(max(tc.wPeriodMin,
TIMER_ACCURACY),tc.wPeriodMax);
//調用timeBeginPeriod函數設置定時器的解析度
timeBeginPeriod(wAccuracy);
//設置定時器
InitializeTimer();
}
}
CCureApp:: ~CCureApp()
{
//結束時鐘
fout 「結束時鐘」 endl;
// 刪除兩個定時器
timeKillEvent(TimerID_1ms);
timeKillEvent(TimerID_2s);
// 刪除設置的解析度
timeEndPeriod(wAccuracy);
}
void CCureApp::InitializeTimer()
{
StartOneMilliSecondTimer();
StartTwoSecondTimer();
}
// 1ms定時器的回調函數,類似於中斷處理程序,一定要聲明為全局PASCAL函數,否則編譯會有問題
void PASCAL OneMilliSecondProc(UINT wTimerID, UINT msg,DWORD dwUser,DWORD dwl,DWORD dw2)
{
// 定義計數器
static int ms = 0;
CCureApp *app = (CCureApp *)dwUser;
// 取得系統時間,以ms為單位
DWORD osBinaryTime = GetTickCount();
//輸出計數器值和當前系統時間
app-fout++ms「:1ms:」
}
// 加裝1ms定時器
void CCureApp::StartOneMilliSecondTimer()
{
if((TimerID_1ms = timeSetEvent(wTimerRes_1ms,
wAccuracy,
// 回調函數
(LPTIMECALBACK) OneMil liSecondProc,
// 用戶傳送到回調函數的數據
(DWORD)this,
/ *周期調用,只使用一次,用TIME_ONESHOT*/
TIME_PERIODIC)) == 0)
{
AfxMessageBox(「不能進行定時!」, MB_OK | MB_ICONASTERISK);
}
else //不等於0表明加裝成功,返回此定時器的句柄
fout 「16ms 計 時:」 endl;
}
利用系統定時中斷
在PC機中採用了可編程定時/計數晶元8253,計數器0工作在方式3,用OUT0產生時鐘信號。OUT0作為中斷請求信號接可編程中斷控制器8259A的IR0(系統中IRQ0)。由於fCLK≈1.19MHz,TCLK≈840ns,因此8253初值為65536時,大約每840ns×65536≈55ms中斷一次。可以讀取計數器的當前計數值,計數器值每減一,代表時間840ns,另加上計數器是否計滿的判斷,則可計算出時間的精確值。
8253的6種工作方式的設置是在初始化時用輸出指令寫控制字來實現的,其中,方式0為在結束計數時中斷。
調用VC++運行庫函數clock(),可以獲得本次程序運行由處理器用去的ms時間,由此可判斷出計數器是否計滿。具體程序代碼如下:
// 延時函數
void Ddelay(unsigned long n)
{
unsigned long Told;
unsigned long nn,old_Clock, new_Clock, low, high, v_8253;
unsigned long old_8253, new_8253, int_Time;
// nn單位: 840ns
nn =(unsigned long)((float)n*1000/840);
// 鎖定8253計數值
_outp(0x43,0x00);
// 讀取8253計數值
low = _inp(0x40);
high = _inp(0x40);
v_8253 = low + 256 * high;
old_8253 = v_8253;
old_Clock=clock();
Told=old_Clock;
int_Time=0;
while(int_Time nn)
{
_outp(0x43,0x00);
low = _inp(0x40);
high = _inp(0x40);
v_8253 = low + 256 * high;
new_8253 = v_8253;
new_Clock=clock();
if(old_8253 new_8253 && new_Clock-Told 55) int_Time=(old_8253-new_8253)+
((new_Clock-old_Clock)/55+1)*65536lu;
else
int_Time=(old_8253-new_8253)+
((new_Clock-old_Clock)/55) * 65536lu;
Told=new_Clock;
}
}
51單片機分頻器C語言
脈衝寬度是一樣的。
偶數的話很簡單,由模N/2 實現一個占空比為1:1的N分配器。
那麼奇數 上面的方法顯然就不行了,當然,分頻的占空比看需求了,沒 如果想要得到占空比為50%奇數分頻,那可以利用上升沿或者下降沿觸發是開始進行模N計數,計數到某一值就給他翻轉,然後在經過(N-1)/2,再次翻轉,從而實現了:((N-1)/2:N)奇數分頻。
你說的3、5你看是按照什麼占空比來做了,如果1:1 那麼高低電平一樣也是可以的。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/304318.html