當前位置:首頁 » 文件傳輸 » 訪問寄存器delay
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

訪問寄存器delay

發布時間: 2022-05-11 10:26:40

❶ 數碼管動態掃描中的delay 函數有什麼作用

該實驗用到實驗板的資源電路圖如下:

其中P0口是段碼,低電平有效。P2口是位碼,高電平有效。P2.0口控制第1個數碼管,一直到P2.7口控制第8個。該板的段碼表如下:

各個數碼管的段碼都是p0口的輸出,即各個數碼管輸入的段碼都是一樣的, 為了使其分別顯示不同的數字, 可採用動態顯示的方式,即先只讓最低位顯示0(含點),經過一段延時,再只讓次低位顯示1,如此類推。由視覺暫留,只要我們的延時時間足夠短,就能夠使得數碼的顯示看起來非常的穩定清楚。過程如下圖。

採用上述方法思路編寫如下:

org 0000h

start: mov a,#08h ;0 ;段碼
mov p0,a
mov p2,#01h ;位碼
lcall delay_1ms

mov a,#0abh ;1
mov p0,a
mov p2,#02h
lcall delay_1ms

mov a,#12h ;2
mov p0,a
mov p2,#04h
lcall delay_1ms

mov a,#22h ;3
mov p0,a
mov p2,#08h
lcall delay_1ms

mov a,#0a1h ;4
mov p0,a
mov p2,#10h
lcall delay_1ms

mov a,#24h ;5
mov p0,a
mov p2,#20h
lcall delay_1ms

mov a,#04h ;6
mov p0,a
mov p2,#40h
lcall delay_1ms

; mov a,#0aah ;7
; mov p0,a
mov p0,#0aah ;感覺用這句和上面兩句實現一樣,可能這種習慣以後會有用吧
mov p2,#80h
lcall delay_1ms

ljmp start

delay_1ms: mov r6,#2
temp: mov r5,#0ffh
djnz r5,$
djnz r6,temp
ret
end

下載到板上得到測結果為從低到高八位分別顯示0到7(含點)。

★ 上述方法逐次給P0或者P2賦值,一方面程序的復雜程度增加,另外一方面會使得程序的靈活性降低。如果要改變顯示的數字,程序改動起來很麻煩。 所以要用51單片機中常用的一種方法:查表法。例如P0口輸出段碼時,我們可以把要顯示的段碼放在一個表格中,然後每次從這個表格裡面取數,送到P0口即可。P2口輸出位碼時,可以把要用的位碼放在另一個表格里,每次從此表中取數,送入P2口。這樣,如果要改變顯示的數字,只需要改變表格裡面的數。

org 0000h

start: mov r7,#0ffh ;r7,r6查表時送入變址寄存器a (因自加1後為0,所以預置ffh)
mov r6,#0ffh
loop: lcall play1 ;調用顯示段碼子程序
lcall play2 ;調用顯示位碼子程序
lcall delay_1ms
cjne a,#80h,loop ;判斷是否到了最左邊的數,即第8個位碼
ajmp start

play1: ;查表求段碼子程序
; mov a,r7
; inc a
; mov r7,a

inc r7 ;這2句和上面三條語句實現功能相同
mov a,r7 ;a在這里做變址寄存器

mov dptr,#table1 ;表首址送dptr,dptr做基址寄存器
movc a,@a+dptr ;基址寄存器加變址寄存器定址
mov p0,a
ret

play2: ;查表求位碼子程序(原理同play1)
mov a,r6
inc a
mov r6,a
mov dptr,#table2
movc a,@a+dptr
mov p2,a
ret

table1: db 08h,0abh,12h,22h,0a1h,24h,04h,0aah ;段碼表
table2: db 01h,02h,04h,08h,10h,20h,40h,80h ;位碼表

delay_1ms: mov r5,#02h ;延時1ms子程序
temp: mov r4,#0ffh
djnz r4,$
djnz r5,temp
ret
end

下載到板上驗證得到預想結果。

--------------------------------------------------------------------------------
C51實現如下(參考了AS的常式):

#include <reg51.h>
#include <intrins.h> // 包含了左移函數_crol_()

void delayms(unsigned char ms); // 延時子程序

unsigned char data dis_digit; // 位選通值, 傳送到P2口用於選通當前數碼管的數值,
// 如等於0x01時,選通P2.0口數碼管

unsigned char code dis_code[11]={0x08,0xab,0x12,0x22,0xa1, // 0,1,2,3, 4
0x24,0x04,0xaa,0x00,0x20, 0xff}; // 5,6,7,8,9, off

unsigned char data dis_buf[8]; // dis_buf 顯於緩沖區基地址

unsigned char data dis_index; // 顯示索引, 用於標識當前顯示的數碼管和緩沖區的偏移量

void main()
{
P0 = 0xff; // 關閉所有數碼管
P2 = 0x00;

dis_buf[0] = dis_code[0];
dis_buf[1] = dis_code[1];
dis_buf[2] = dis_code[2];
dis_buf[3] = dis_code[3];
dis_buf[4] = dis_code[4];
dis_buf[5] = dis_code[5];
dis_buf[6] = dis_code[6];
dis_buf[7] = dis_code[7];

dis_digit = 0x01; // 首先選通P2.0
dis_index = 0; // 當前偏移量為0

while(1)
{
P0 = dis_buf[dis_index]; // 段碼送P0口
P2 = dis_digit; // 選能位(即位碼)
delayms(1); // 延時
dis_digit = _crol_(dis_digit, 1); // 位選通左移, 下次選通下一位
dis_index++; // 下一個段碼

dis_index &= 0x07; // 見注釋
}

}
void delayms(unsigned char ms) // 延時子程序(晶振12M)
{
unsigned char i;
while(ms--)
{
for(i = 0; i < 120; i++);
}
}

★ 注釋: 此句作用是8個數碼管全部掃描完一遍之後,再回到第一個開始下一次掃描。寫回一般形式:dis_index = dis_index & 0x07 。這種方法挺新,第一次見到,十六進制的07就是二進制的00000111,這樣通過與操作可能控制循環了。比如dis_index 經第一次循環後值為00000001,和0x07與操作後值不變仍為0x01,第二次循環時,其值為0為0x02,與0x07後仍為0x02,一直到其值增為0x07時還是不變的,但再次循環後其值為0x80,再與0x07後就變成0x00了,這樣又從初始循環了。此句可用 if (dis_index == 8) dis_index = 0 代替,效果一樣。

★ 通過C51用上述方法實現時,其段碼放在了數組dis_code[11]中,再通過緩沖區數組dis_buf[]將程序中要調用的值裝入,這樣就可以用下標(偏移量)訪問了。這樣看上去有些繁鎖,但其思路比較清楚,結構上也很明了,具有通用性,便於擴展。

★ 另外只要把程序中的延時加長,如delayms(1000),下載到板上就可以看到實際上數碼管是由低位到高位逐位顯示的。

--------------------------------------------------------------------------------
若單單就實現這個功能而言,可以直接調入段碼數組dis_code[11]中下標從0到7的值,而不必再設置緩沖數組dis_buf[],實現如下:

#include <reg51.h>
#include <intrins.h> //_crol_()用

void delayms(unsigned char ms); //延時子程序

unsigned char data dis_digit; //位選通值, 傳送到P2口用於選通當前數碼管的數值,
//如等於0x01時,選通P2.0口數碼管

unsigned char code dis_code[11]={0x08,0xab,0x12,0x22,0xa1, // 0,1,2,3,4
0x24,0x04,0xaa,0x00,0x20, 0xff}; // 5,6,7,8,9,off

unsigned char data dis_index; //顯示索引, 用於標識當前顯示的數碼管和緩沖區的偏移量

void main()
{
P0 = 0xff; // 關閉所有數碼管
P2 = 0x00;

dis_index = 0; // 當前偏移量為0
dis_digit = 0x01; // 選通P2.0

while(1)
{
P0 = dis_code[dis_index]; // 段碼送P0口
P2 = dis_digit; // 位碼送P2口
delayms(1);

dis_digit = _crol_(dis_digit, 1); // 位選通左移, 下次選通下一位

dis_index++;
dis_index &= 0x07;
}
}
void delayms(unsigned char ms) // 延時子程序(晶振12M)
{
unsigned char i;
while(ms--)
{
for(i = 0; i < 120; i++);
}
}

★ 通本來是想通過以下方式實現一次循環的:

for (dis_index = 0; dis_index < 8; dis_index++)
{
P0 = dis_code[dis_index]; // 段碼送P0口
P2 = dis_index+1; // 位碼送P2口
delayms(1);
}

可得到的總是錯誤的結果:第0位到第2位這三位顯示的是三個8,第3位顯示的是7,高四位沒有顯示。加長延時逐位觀察也沒有發現錯誤的規律,對Keil的調試也不熟悉,先把問題留到這,待找出原因後再補上。

[2006.5.2] 找出原因啦,補上:

今天又看了一下,找到上面的錯誤出在哪了。當時是想用dis_index的值做為位碼的,即第一位顯示0時,段碼為dis_code[0], 即dis_index值為0, 此時位碼值為1。第二位顯示1時,段碼為dis_code[1],即dis_index值為1,此時位碼值為2。所以就簡單用了個加1運算,將P0口的偏移值與P2口的位碼聯系起來。但仔細想一下位碼的原理,上述方法顯然是錯的,只要再驗證一步就明白了,即當第3位顯示2時,段碼為dis_code[2], dis_index值為2,加1後為3,按上述方法時就將這個3作為了位碼,而正確的位碼應該是4 (00000100B)。所以出錯。實際上這個對應關系是有的,但不是簡簡單單的加1,位碼應該是2的dis_index次冪。即:
0--1
1--2
2--4
3--8
4--16 ……
冪次運算函數flaot pow(float x, float y)包含在math.h中, 返回值為xy (float型):

for (dis_index = 0; dis_index < 8; dis_index++)
{
P0 = dis_code[dis_index]; // 段碼送P0口
P2 = (char) pow(2, dis_index); // 位碼送P2口
delayms(255);
}

再次下載到板上發現仍有問題, 即延時很小的時候顯示混亂,但加大延時時間(如程序中的值)可以觀查到數碼管是按位正確顯示的。另外用這種方法產生的代碼量也很大(從寫入速度看,很明顯)。這里僅提出了一個思路,只在此實驗中適用,意義不大,到此為止。

[補充結束]

--------------------------------------------------------------------------------

AS中紿出的常式是利用定時中斷做的延時,參考修改到我的板上,程序如下:

#include <reg51.h>
#include <intrins.h> // 包含了左移函數_crol_()

unsigned char data dis_digit; // 位選通值, 傳送到P2口用於選通當前數碼管的數值,
// 如等於0x01時,選通P2.0口數碼管

unsigned char code dis_code[11]={0x08,0xab,0x12,0x22,0xa1, // 0,1,2,3,4
0x24,0x04,0xaa,0x00,0x20, 0xff}; // 5,6,7,8,9,off

unsigned char data dis_buf[8]; // dis_buf 顯於緩沖區基地址

unsigned char data dis_index; // 顯示索引, 用於標識當前顯示的數碼管和緩沖區的偏移量

void main()
{
P0 = 0xff; //關閉所有數碼管
P2 = 0x00;

TMOD = 0x01; // 00000001B 定時計數器0工作在方式1,16位定時器/計數器
TH0 = 0xFC;
TL0 = 0x17; // 預置初值 FC17H=64535D, 216-64535=1001us=1ms

IE = 0x82; // 10000010B T0溢出中斷允許

dis_buf[0] = dis_code[0x0];
dis_buf[1] = dis_code[0x1];
dis_buf[2] = dis_code[0x2];
dis_buf[3] = dis_code[0x3];
dis_buf[4] = dis_code[0x4];
dis_buf[5] = dis_code[0x5];
dis_buf[6] = dis_code[0x6];
dis_buf[7] = dis_code[0x7];

dis_digit = 0x01; // 選通第0位數碼管
dis_index = 0; // 偏移初值為0

TR0 = 1; // 啟動T0
while(1); // 循環等待中斷

}

void timer0() interrupt 1 // 定時器0中斷服務程序, 用於數碼管的動態掃描

{
TH0 = 0xFC; // 發生中斷定時/計數器重裝初值
TL0 = 0x17; // 感覺此處(及上)應該是0x18,而不是17,分析如下

P2 = 0x00; // 先關閉所有數碼管
P0 = dis_buf[dis_index]; // 段碼送P0口
P2 = dis_digit; // 位碼送P2口

dis_digit = _crol_(dis_digit,1); // 位選通值左移, 下次中斷時選通下一位數碼管
dis_index++;

dis_index &= 0x07; // 8個數碼管全部掃描完一遍之後,再回到第一個開始下一次掃描
}

★ 定時器/計數器的輸入脈沖周期與機器周期一樣, 為時鍾振盪頻率的1/12。晶振用12M時,輸入脈沖周期間隔為1us。機器周期為 1us。設T0的初值為X,計算初值的方法:本例中定時器用方式1,是16位的定時器,即最大值為216=65536,超過此值將發生溢出,引起中斷,進入中斷處理程序。這里要讓其延時1ms,即1000us, 則有式216-X=1000,可得X=64536,換算為16進制為FC18,即初值TH0=0xFC,TL0=0x18。即定時器由64536開始計數,經1000次計數後值為65536,將發生定時中斷,再進入中斷處理子程序後,重新裝和初值,如此循環下去。
而在上例中其裝入的初值並非FC18(64536),而是FC17(64535)。我想大概認為其計數范圍在0~65565的原因吧,我也想過這個問題,是用216-計數初值=中斷間隔 呢,還是用(216-1)-計數初值=中斷間隔呢? 隨手查了幾本書, 說法不一,不過用前者的較多, 我自己也認為前者比較合理, 因為在計算機中16位的二進制不能表示65536, 在各位均為1時表示的值為65535, 即65535H=1111111111111111B, 也可以說65536是溢出得到的。而何時響應中斷就成了關鍵,拿上例來說,如設初值為64535(FC17),則計數到65535時,已經計數為1000個,即1ms,但此時並未發生溢出,因此也沒有觸發中斷。而是在下一個計數後才發生。確切值應為1001us。若初值為64536(FC18),則恰好為所需值,所以上例中的初值應該用FC18而不是FC17。這僅僅是我自己的一點看法,至於是不是這樣,還有待進一步考證。

--------------------------------------------------------------------------------
最終下載到實驗板上結果:

######################################補充########################################

用Proteus模擬結果如下(某一狀態的截圖):

★ 該電路段碼是按與板上接法對應的,即按前面的段碼表次序連接。另外這個八位的模擬數碼管最左端是第一位,最右端是第八位,與板上的順序相反,所以接為了統一,該圖以板為准連接。上圖不加上拉電阻也可模擬出結果,只是P0口高電平顯示為灰,即高阻。

c語言訪問寄存器的問題

C語言在X86下沒有直接操作寄存器的代碼,雖然可以使用register關鍵字聲明寄存器變數,但無法指定使用哪一個寄存器;
使用嵌入式匯編可以達到如題所述目的。例如
__asm(mov eax,#01);

❸ 網路分析中Delay是指信號經過DUT的輸入輸出時間差嗎

你好,不是。Delay是指通過DUT的信號的各個頻率分量之間的時延差,對應相頻特性,兩個不一樣的,希望能幫到你!

❹ stm32中Delay()函數延時的時間是怎麼計算的

單片機編程過程中經常用到延時函數,最常用的莫過於微秒級延時delay_us(

)和毫秒級delay_ms(

)。1.普通延時法這個比較簡單,讓單片機做一些無關緊要的工作來打發時間,經常用循環來實現,不過要做的比較精準還是要下一番功夫。下面的代碼是在網上搜到的,經測試延時比較精準。//粗延時函數,微秒

void delay_us(u16 time)

{

u16 i=0;

while(time--)

{

i=10; //自己定義

while(i--) ;

}

}

//毫秒級的延時

void delay_ms(u16 time)

{

u16 i=0;

while(time--)

{

i=12000; //自己定義

while(i--) ;

}

}2.SysTick 定時器延時CM3 內核的處理器,內部包含了一個SysTick

定時器,SysTick 是一個24 位的倒計數定時器,當計到0 時,將從RELOAD

寄存器中自動重裝載定時初值。只要不把它在SysTick

控制及狀態寄存器中的使能位清除,就永不停息。SysTick 在STM32

的參考手冊裡面介紹的很簡單,其詳細介紹,請參閱《Cortex-M3 權威指南》。

這裡面也有兩種方式實現:a.中斷方式

如下,定義延時時間time_delay,SysTick_Config()定義中斷時間段,在中斷中遞減time_delay,從而實現延時。

volatile unsigned long time_delay; //

延時時間,注意定義為全局變數

//延時n_ms

void delay_ms(volatile unsigned long nms)

{

//SYSTICK分頻--1ms的系統時鍾中斷

if (SysTick_Config(SystemFrequency/1000))

{

while (1);

}

time_delay=nms;//讀取定時時間

while(time_delay);

SysTick->CTRL=0x00; //關閉計數器

SysTick->VAL =0X00; //清空計數器

}

//延時nus

void delay_us(volatile unsigned long nus)

{

//SYSTICK分頻--1us的系統時鍾中斷

if (SysTick_Config(SystemFrequency/1000000))

{

while (1);

}

time_delay=nus;//讀取定時時間

while(time_delay);

SysTick->CTRL=0x00; //關閉計數器

SysTick->VAL =0X00; //清空計數器

} //在中斷中將time_delay遞減。實現延時void

SysTick_Handler(void)

{

if(time_delay)

time_delay--;

❺ 51單片機C語言程序中延時函數delay的原理是什麼

原理:只是執行一些所謂的「無實際意義的指令」,如縮放或執行一個int自加,簡單地說,就像高中數學中的「乘法原理」一樣,很容易迅速增加上面提到的「無意義指令」的數量

關於大小的值:如果是在C語言中,該值不僅與水晶振動、單片機本身的速度,但也與C的編譯器,所以,雖然這個值可以精確計算,但大多數情況下,程序員是經驗值。

當然,如果你在匯編中編程,情況就不同了,因為每條指令使用一定數量的機器周期,你當然可以根據所有指令使用的總時間來計算特定延遲的總時間。

(5)訪問寄存器delay擴展閱讀:

定義延遲XMS毫秒的延遲函數

Voiddelay(unsignedintXMS)//XMS表示需要延遲的毫秒數

無符號intx,y;

For(x=XMS;X0;X-)

For(y=110;Y」0;Y-);

使用:

VoidDelay10us(ucharMs)

Uchar數據我;

(;女士「0;------Ms)

對於(I = 26)我> 0;我-);

I=[(延遲值-1.75)*12/ms-15]/4

❻ 用戶態如何訪問寄存器空間

一般而言,訪問寄存器需要在內核態完成。兩種方式:一種是IO埠,一種是內存映射。如果內核把寄存器空間映射的到了內核地址空間,進而又把內核地址空間映射到了進程地址空間的話,應用程序就可以在用戶態通過訪問自己進程空間的映射來訪問寄存器了。要做到這一點,一般需要驅動程序和內核的配合。

❼ 在i2c匯流排中delay有什麼用

在一個寫數據的操作之後需要delay,因為晶元需要一點時間來將數據從緩沖區寫入寄存器,具體的時間在晶元的datasheet中一般有規定

❽ 組態王6.55寄存器DELAY是什麼

****地址。建議使用Modscan先測試一下。40001 I/O整型 BYTE。智能電表讀char的話,可能是讀不到的

❾ 單片機中C語言中斷怎麼求

interrupt 後面的點是中斷號。重點我給你解釋下using。

這是C51編譯器擴展的關鍵字。用來選擇80c51單片機中不同的寄存器組,你也知道R0-R7總共有4組,那麼using 後面的數字也就是0-3范圍里的一個數了。如果不需要using的話,編譯器會自動選擇一組寄存器作為絕對寄存器訪問的。
using對代碼是有一定的影響的。
給你說個簡單的例子,你可以想下,
如果定義
void time0() interrupt 1 using 1
假設,我們又在中斷里調用了一個delay();這個delay是起延時作用。
那麼,我們就需要確保我們使用的寄存器組是同一組,否則,就會出現混亂。

❿ DELAY是什麼寄存器

DELAY?字面上看是延時的意思...組太軟體的話,可能是通訊超時或者通訊響應時間吧。