亚洲春色中文字幕久久久-三上亚,一吻二脱三床四吻胸,国产真实伦对白视频全集,在线毛片观看,精品成品入口黄网,国产毛aⅴ片久久久,亚洲AV色香蕉一区二区三区老师,萧皇后A级艳片,色情日本视频更新,99久久亚洲精品日本无码

 找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 330|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

第9章 綜合練習(xí)9.5 9.6 9.7

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:1167894 發(fā)表于 2026-4-13 10:03 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式

9.5不同數(shù)據(jù)類型間的相互轉(zhuǎn)換
C語言中,不同數(shù)據(jù)類型之間是可以混合運(yùn)算的。當(dāng)表達(dá)式中的數(shù)據(jù)類型不一致時(shí),首先轉(zhuǎn)換為同一種類型,然后再進(jìn)行計(jì)算。C語言有兩種方法實(shí)現(xiàn)類型轉(zhuǎn)換,一是自動(dòng)類型轉(zhuǎn)換,另外一種是強(qiáng)制類型轉(zhuǎn)換。
不同數(shù)據(jù)類型之間轉(zhuǎn)換的主要原則是:短字節(jié)的數(shù)據(jù)向長(zhǎng)字節(jié)數(shù)據(jù)轉(zhuǎn)換。
比如:unsigned char a;  unsigned int b;  unsigned int c;  c = a *b;
在運(yùn)算的過程中,程序會(huì)自動(dòng)全部按照unsigned int型來計(jì)算。比如a=10b=200c的結(jié)果就是2000。那當(dāng)a=100b=700,那c70000嗎?新手最容易犯這種錯(cuò)誤,要注意每個(gè)變量類型的取值范圍,c的數(shù)據(jù)類型是unsigned int型,取值范圍是0~65535,而70000超過65535了,其結(jié)果會(huì)溢出,最終c的結(jié)果是(70000 - 65536) = 4464
那要想讓c正常獲得70000這個(gè)結(jié)果,需要把c定義成一個(gè)unsigned long型。如果寫成:unsigned char a=100;  unsigned int b=700;  unsigned long c=0;  c = a*b;有做過實(shí)驗(yàn)的同學(xué),會(huì)發(fā)現(xiàn)這個(gè)c的結(jié)果還是4464,這個(gè)是個(gè)什么情況呢?
請(qǐng)注意,C語言不同類型運(yùn)算的時(shí)候數(shù)值會(huì)轉(zhuǎn)換同一類型運(yùn)算,但是每一步運(yùn)算都會(huì)進(jìn)行識(shí)別判斷,不會(huì)進(jìn)行一個(gè)總的分析判斷。比如這段代碼中ab相乘的時(shí)候,是按照unsigned int類型運(yùn)算的,運(yùn)算的結(jié)果也是unsigned int類型的4464,只是最終把unsigned int類型4464賦值給了一個(gè)unsigned long型的變量而已。在運(yùn)算的時(shí)候如何避免這類問題的產(chǎn)生呢?可以采用強(qiáng)制類型轉(zhuǎn)換的方法。
在一個(gè)變量前邊加上一個(gè)數(shù)據(jù)類型名,并且這個(gè)類型名用小括號(hào)括起來,就表示把這個(gè)變量強(qiáng)制轉(zhuǎn)換成括號(hào)里的類型。如 c = (unsigned long)a * b;由于強(qiáng)制類型轉(zhuǎn)換運(yùn)算符優(yōu)先級(jí)高于*,所以這個(gè)地方的運(yùn)算是先把a轉(zhuǎn)換成一個(gè)unsigned long型的變量,而后與b相乘,根據(jù)C語言的規(guī)則b會(huì)自動(dòng)轉(zhuǎn)換成一個(gè)unsigned long型的變量,而后運(yùn)算完畢結(jié)果也是一個(gè)unsigned long型的,最終賦值給了c
不同類型變量之間的相互賦值,短字節(jié)類型變量向長(zhǎng)字節(jié)類型變量賦值時(shí),其值保持不變,比如unsigned char a=100;  unsigned int b=700;  b=a;那么最終b的值就是100了。但是如果程序是unsigned char a=100;  unsigned int b=700;  a=b;那么a的值僅僅是取了b的低8位,首先要把700變成一個(gè)16位的二進(jìn)制數(shù)據(jù),然后取它的低8位出來,也就是188,這就是長(zhǎng)字節(jié)類型給短字節(jié)類型賦值的結(jié)果,會(huì)從長(zhǎng)字節(jié)類型的低位開始截取剛好等于短字節(jié)類型長(zhǎng)度的位,然后賦給短字節(jié)類型。
51單片機(jī)里邊,有一種特殊情況,就是bit類型的變量,這個(gè)bit類型的強(qiáng)制類型轉(zhuǎn)換,是不符合上邊講的這個(gè)原則的,比如bit a=0;  unsigned char b;  a=(bit)b;使用bit做強(qiáng)制類型轉(zhuǎn)換,不是取b的最低位,而是它會(huì)判斷b這個(gè)變量是0還是非0的值,如果b0,那么a的結(jié)果就是0,如果b是任意非0的其它值,那么a的結(jié)果都是1
9.6定時(shí)器中斷響應(yīng)調(diào)整
6.5.2章節(jié)有一個(gè)數(shù)碼管秒表顯示程序,那個(gè)程序是1秒數(shù)碼管加1,但是細(xì)心的讀者做了實(shí)驗(yàn),經(jīng)過長(zhǎng)時(shí)間運(yùn)行會(huì)發(fā)現(xiàn),和實(shí)際的時(shí)間有了較大誤差了,那如何去調(diào)整這種誤差呢?要解決問題,先找到問題是什么原因造成的。
先對(duì)前面講過的中斷內(nèi)容做一個(gè)較深層次的補(bǔ)充。還是講解中斷的那個(gè)場(chǎng)景,當(dāng)在看電視的時(shí)候,突然發(fā)生了水開的中斷,必須去提水的時(shí)候,第一,從電視跟前跑到廚房需要一定的時(shí)間,第二,因?yàn)榭吹碾娨暿侵悄軘?shù)字電視,因此在去提水之前可以使用遙控器將電視進(jìn)行暫停操作,方便回來后繼續(xù)從剛才的劇情往下進(jìn)行。暫停電視,跑到廚房提水,這一點(diǎn)點(diǎn)時(shí)間是很短的,在實(shí)際生活中可以忽略不計(jì),但是在單片機(jī)秒表程序中,誤差是會(huì)累計(jì)的,每1秒鐘都差了幾個(gè)微秒,時(shí)間一久,造成的累計(jì)誤差就不可小覷了。
單片機(jī)系統(tǒng)里,硬件進(jìn)入中斷需要一定的時(shí)間,大概是幾個(gè)機(jī)器周期,還要進(jìn)行原始數(shù)據(jù)保護(hù),就是把進(jìn)中斷之前程序運(yùn)行的一些變量先保存起來,專業(yè)術(shù)語叫做中斷壓棧,進(jìn)入中斷后,重新給定時(shí)器THTL賦值,也需要幾個(gè)機(jī)器周期,這樣下來就會(huì)消耗一定的時(shí)間,得把這些時(shí)間補(bǔ)償回來。
方法一,使用軟件debug進(jìn)行補(bǔ)償。
前邊講過使用debug來觀察程序運(yùn)行時(shí)間,那可以把2次進(jìn)入中斷的時(shí)間間隔觀察出來,看看和實(shí)際定時(shí)的時(shí)間相差了幾個(gè)機(jī)器周期,然后在進(jìn)行定時(shí)器初值賦值的時(shí)候,進(jìn)行一個(gè)調(diào)整。Kingst51開發(fā)板用的是11.0592M的晶振,發(fā)現(xiàn)差了幾個(gè)機(jī)器周期,就把定時(shí)器初值加上幾個(gè)機(jī)器周期,這樣就相當(dāng)于進(jìn)行了一個(gè)補(bǔ)償。
方法二,使用累計(jì)誤差計(jì)算出來。
有的時(shí)候,除了程序本身存在的誤差外,硬件精度也可能會(huì)影響到時(shí)鐘的精度,比如晶振,會(huì)隨著溫度變化出現(xiàn)溫漂現(xiàn)象,就是實(shí)際值和標(biāo)稱值要差一點(diǎn)。那么還可以采取累計(jì)誤差的方法來提高精度。讓時(shí)鐘運(yùn)行半個(gè)小時(shí)或者一個(gè)小時(shí),看看最終時(shí)間差了幾秒,然后算算一共進(jìn)了多少次中斷,把差的幾秒平均分配到每次中斷中,就可以實(shí)現(xiàn)時(shí)鐘的調(diào)整。這個(gè)世界上本就沒有絕對(duì)的精確,只能在一定程度上提高精確度,但是永遠(yuǎn)都不會(huì)使誤差為零。
9.7字節(jié)操作修改位的技巧
在編程時(shí),有的情況下需要改變一個(gè)字節(jié)中的某一位或者幾位,但是又不想改變其它位原有的值,該如何操作呢?
例如學(xué)習(xí)定時(shí)器的時(shí)候遇到一個(gè)寄存器TCON,這個(gè)寄存器是可以進(jìn)行位操作的,可以直接寫TR0=1;TR0TCON的一個(gè)位。還有一個(gè)寄存器TMOD,這個(gè)寄存器是不支持位操作的,那如果要使用T0的模式1,希望達(dá)到的效果是TMOD的低4位是0b0001,但如果直接寫成TMOD = 0x01的話,實(shí)際上已經(jīng)同時(shí)操作到了高4位,即屬于T1的部分,設(shè)置成了0b0000,如果T1定時(shí)器沒有用到的話,那隨便怎么樣都行,但是如果程序中既用到了T0,又用到了T1,那設(shè)置T0的同時(shí)已經(jīng)干擾到了T1的模式配置,這是不希望看到的結(jié)果。
在這種情況下,就可以用前邊學(xué)過的&|運(yùn)算了。對(duì)于二進(jìn)制位操作來說,不管該位原來的值是0還是1,它跟0進(jìn)行&運(yùn)算,得到的結(jié)果都是0,而跟1進(jìn)行&運(yùn)算,將保持原來的值不變;不管該位原來的值是0還是1,它跟1進(jìn)行|運(yùn)算,得到的結(jié)果都是1,而跟0進(jìn)行|運(yùn)算,將保持原來的值不變。
利用上述這個(gè)規(guī)律,就可以著手解決剛才的問題了。如果現(xiàn)在要設(shè)置TMOD使定時(shí)器0工作在模式1下,又不干擾定時(shí)器1的配置,可以進(jìn)行這樣的操作:TMOD = TMOD & 0xF0; TMOD = TMOD | 0x01;第一步與0xF0&運(yùn)算后,TMOD的高4位不變,低4位清零,變成了0bxxxx0000;然后再進(jìn)行第二步與0x01進(jìn)行|運(yùn)算,那么高7位均不變,最低位變成1了,這樣就完成了只將低4位的值修改位0b0001,而高4位保持原值不變的任務(wù),即只設(shè)置了T0而不影響T1
另外,在C語言中,a &= b;等價(jià)于a = a&b;同理,a |= b;等價(jià)于a = a|b;那么剛才的一段代碼就可以寫成TMOD &= 0xF0;TMOD |= 0x01這樣的簡(jiǎn)寫形式。這種寫法可以一定程度上簡(jiǎn)化代碼,是C語言常用的一種編程風(fēng)格。

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表