久久99精品久久久久久琪琪,久久人人爽人人爽人人片亞洲,熟妇人妻无码中文字幕,亚洲精品无码久久久久久久

上嵌淺談C語言學習心得

時間:2019-05-15 10:25:28下載本文作者:會員上傳
簡介:寫寫幫文庫小編為你整理了多篇相關的《上嵌淺談C語言學習心得》,但愿對你工作學習有幫助,當然你在寫寫幫文庫還可以找到更多《上嵌淺談C語言學習心得》。

第一篇:上嵌淺談C語言學習心得

上嵌淺談C語言學習心得

上嵌小編總結了C語言學習的一些心得,希望能幫助到大家

學習C語言已經好幾年,對C也算得上半個入門者,期間也寫過一些自娛自樂的代碼。其實個人認為無論學習什么語言,最重要的是掌握習編程思想,然而C語言一種學習編程思想的基礎語言。所以,C語言的重要性不言而喻。

一、課本

無論用的是什么書,要學好C語言,把書上的每一個例題、習題的代碼讀懂,這是學C最基本的要求。弄懂每一章的內容是什么?在C語言中有什么用?并嘗試修改每一個例題的代碼,采用不同的代碼來實現題目的要求。

二、課堂

課堂上要講授許多關于c語言的語法規則,聽起來十分枯燥無味,也不容易記住,死記硬背是不可取的。然而要使用c語言這個工具解決實際問題,又必須掌握它。通過多次上機練習,對于語法知識有了感性的認識,加深對它的理解,在理解的基礎上就會自然而然地掌握c語言的語法規定。對于一些內容自己認為在課堂上聽懂 了,但上機實踐中會發現原來理解的偏差,這是由于大部分學生是初次接觸程序設計,缺乏程序設計的實踐所致。學習c語言不能停留在學習它的語法規則,而是利用學到的知識編寫c語言程序,解決實際問題。即把c語言作為工具,描述解決實際問題的步驟,由計算機幫助我 們解題。只有通過上機才能檢驗自己是否掌握c語言、自己編寫的程序是否能夠正確地解題。通過上機實驗來驗證自己編制的程序是否正確,恐怕是大多數同學在完成老師作業時的心態。但是在程序設計領域里這是一定要克服的傳統的、錯誤的想法。因為在 這種思想支配下,可能你會想辦法去“掩蓋”程序中的錯誤,而不是盡可能多地發現程序中存在的問題。自己編好程序上機調試運行時,可能有很多你想不到的情況 發生,通過解決這些問題,可以逐步提高自己對c語言的理解和程序開發能力。

三、筆記

無論學習什么知識,筆記是重點,俗話說:好記性不如爛筆頭。一個認真學習的人,總是記了很多筆記的,想學好編程,你的筆記本上總有課本上的每一個例題代碼的核心部分。以及八大經典的算法舉例,遞推、遞歸、窮舉、貪心、分治、動規、迭代、分枝。

四、交流

想學好C語言,交流是必須的,尤其是學習C語言的新手,這里,我向大家推介——百度C語言貼吧,這里有很多的學習者,也有很多高手,在這里你能學到課本以及課堂上學不到的東西。和他人交流也是很重要的。

五、上機練習

這是學習好C語言的關重要的環節,無論你編程學得多好,上機實現才是目的,所以,不怕要辛苦,把你的每一段代碼都敲進計算機,讓計算機來實現,這樣有助于 你對程序的理解,并試著修改你的代碼,讓你的代碼更精簡,效率更高。平時沒事的時候,在計算機上多敲代碼,一個編程厲害的高手,他的計算機上會有很多代碼。

版權歸“上嵌”所有,如有轉載,請注明版權擁有者。

第二篇:C語言學習心得

這個我從eehome貼過來的。寫的非常的好。我們用學單片機不要停在演示的基礎上。只能讓單片機完成局部事。這樣我們永遠不會走出流水燈地獄!!

學習單片機也已經有幾年了,藉此機會和大家聊一下我學習過程中的一些經歷和想法吧。也感謝一線工人提供了這個機會。希望大家有什么好的想法和建議都直接跟帖說出來。畢竟只有交流才能夠碰撞出火花來^_^。

。“賣弄”也好,“吹噓”也罷,我只是想認真的寫寫我這一路走來歷經的總總,把其中值得注意,以及經驗的地方寫出來,權當是我對自己的一個總結吧。而作為看官的你,如果看到了我的錯誤,還請一定指正,這樣對我以及其它讀者都有幫助,而至于你如果從中能夠收獲到些許,那便是我最大的欣慰了。姑妄言之,姑妄聽之。如果有啥好的想法和建議一定要說出來。? 幾年前,和眾多初學者一樣,我接觸到了單片機,立刻被其神奇的功能所吸引,從此不能自拔。很多個日夜就這樣陪伴著它度過了。期間也遇到過非常多的問題,也一度被這些問題所困惑??等到回過頭來,看到自己曾經走過的路,唏噓不已。經常混跡于論壇里,也看到了很多初學者發的求助帖子,看到他們走在自己曾走過的彎路上,忽然想到了自己的那段日子,心里竟然莫名的沖動,凡此總總,我總是盡自己所能去回帖。很多時候,都想寫一點什么東西出來,希望對廣大的初學者有一點點幫助。但總是不知從何處寫起。今天借一線工人的臺,唱一唱我的戲

一路學習過來的過程中,幫助最大之一無疑來自于網絡了。很多時候,通過網絡,我們都可以獲取到所需要的學習資料。但是,隨著我們學習的深入,我們會慢慢發現,網絡提供的東西是有限度的,好像大部分的資料都差不多,或者說是適合大部分的初學者所需,而當我們想更進一步提高時,卻發現能夠獲取到的資料越來越少,相信各位也會有同感,鋪天蓋地的單片機資料中大部分不是流水燈就是LED,液晶,而且也只是僅僅作功能性的演示。于是有些人選擇了放棄,或者是轉移到其他興趣上面去了,而只有少部分人選擇了繼續摸索下去,結合市面上的書籍,然后在網絡上鍥而不舍的搜集資料,再從牛人的只言片語中去體會,不斷動手實踐,慢慢的,也摸索出來了自己的一條路子。當然這個過程必然是艱辛的,而他學會了之后也不會在網絡上輕易分享自己的學習成果。如此惡性循環下去,也就不難理解為什么初級的學習資料滿天飛,而深入一點的學習資料卻很少的原因了。相較于其他領域,單片機技術的封鎖更加容易。盡管已經問世了很多年了,有價值的資料還是相當的欠缺,大部分的資料都是止于入門階段或者是簡單的演示實驗。但是在實際工程應用中卻是另外一回事。有能力的高手無暇或者是不愿公開自己的學習經驗。

很多時候,我也很困惑,看到國外愛好者毫不保留的在網絡上發布自己的作品,我忽然感覺到一絲絲的悲哀。也許,我們真的該轉變一下思路了,幫助別人,其實也是在幫助自己。啰啰嗦嗦的說了這么多,相信大家能夠明白說的是什么意思。在接下來的一段日子里,我將會結合電子工程師之家舉辦的主題周活動寫一點自己的想法。盡可能從實用的角度去講述。希望能夠幫助更多的初學者更上一層樓。而關于這個主題周的最大主題我想了這樣的一個名字“從單片機初學者邁向單片機工程師”。名字挺大挺響亮,給我的壓力也挺大的,但我會努力,爭取使這樣的一系列文章能夠帶給大家一點幫助,而不是看后大跌眼鏡。這樣的一系列文章主要的對象是初學者,以及想從初學者更進一步提高的讀者。而至于老手,以及那些牛XX的人,希望能夠給我們這些初學者更多的一些指點哈~@_@

我們首先來看第一章節

從這一章開始,我們開始邁入單片機的世界。在我們開始這一章具體的學習之前,有必要給大家先說明一下。在以后的系列文章中,我們將以51內核的單片機為載體,C語言為編程語言,開發環境為KEIL uv3。至于為什么選用C語言開發,好處不言而喻,開發速度快,效率高,代碼可復用率高,結構清晰,尤其是在大型的程序中,而且隨著編譯器的不斷升級,其編譯后的代碼大小與匯編語言的差距越來越小。而關于C語言和匯編之爭,就像那個啥,每隔一段時間總會有人挑起這個話題,如果你感興趣,可以到網上搜索相關的帖子自行閱讀。不是說匯編不重要,在很多對時序要求非常高的場合,需要利用匯編語言和C語言混合編程才能夠滿足系統的需求。在我們學習掌握C語言的同時,也還需要利用閑余的時間去學習了解匯編語言。

1.從點亮LED(發光二極管)開始

在市面上眾多的單片機學習資料中,最基礎的實驗無疑于點亮LED了,即控制單片機的I/O的電平的變化。

如同如下實例代碼一般

void main(void){ LedInit();While(1){ LED = ON;DelayMs(500);LED = OFF;DelayMs(500);} }

程序很簡單,從它的結構可以看出,LED先點亮500MS,然后熄滅500MS,如此循環下去,形成的效果就是LED以1HZ的頻率進行閃爍。下面讓我們分析上面的程序有沒有什么問題。

看來看出,好像很正常的啊,能有什么問題呢?這個時候我們應該換一個思路去想了。試想,整個程序除了控制LED = ON ; LED = OFF; 這兩條語句外,其余的時間,全消耗在了DelayMs(500)這兩個函數上。而在實際應用系統中是沒有哪個系統只閃爍一只LED就其它什么事情都不做了的。因此,在這里我們要想辦法,把CPU解放出來,讓它不要白白浪費500MS的延時等待時間。寧可讓它一遍又一遍的掃描看有哪些任務需要執行,也不要讓它停留在某個地方空轉消耗CPU時間。

從上面我們可以總結出

(1)無論什么時候我們都要以實際應用的角度去考慮程序的編寫。

(2)無論什么時候都不要讓CPU白白浪費等待,尤其是延時(超過1MS)這樣的地方。

下面讓我們從另外一個角度來考慮如何點亮一顆LED。先看看我們的硬件結構是什么樣子的。

我手上的單片機板子是電子工程師之家的開發的學習板。就以它的實際硬件連接圖來分析吧。如下圖所示

(原文件名:led.jpg)

引用圖片

一般的LED的正常發光電流為10~20MA而低電流LED的工作電流在2mA以下(亮度與普通發光管相同)。在上圖中我們可知,當Q1~Q8引腳上面的電平為低電平時,LED發光。通過LED的電流約為(VCC-Vd)/ RA2。其中Vd為LED導通后的壓降,約為1.7V左右。這個導通壓降根據LED顏色的不同,以及工作電流的大小的不同,會有一定的差別。下面一些參數是網上有人測出來的,供大家參考。紅色的壓降為1.82-1.88V,電流5-8mA,綠色的壓降為1.75-1.82V,電流3-5mA,橙色的壓降為1.7-1.8V,電流3-5mA 蘭色的壓降為3.1-3.3V,電流8-10mA,白色的壓降為3-3.2V,電流10-15mA,(供電電壓5V,LED直徑為5mm)

74HC573真值表如下:

(原文件名:74hc573.jpg)

引用圖片

通過這個真值表我們可以看出。當OutputEnable引腳接低電平的時候,并且LatchEnable引腳為高電平的時候,Q端電平與D端電平相同。結合我們的LED硬件連接圖可以知道LED_CS端為高電平時候,P0口電平的變化即Q端的電平的變化,進而引起LED的亮滅變化。由于單片機的驅動能力有限,在此,74HC573的主要作用就是起一個輸出驅動的作用。需要注意的是,通過74HC573的最大電流是有限制的,否則可能會燒壞74HC573這個芯片。

上面這個圖是從74HC573的DATASHEET中截取出來的,從上可以看出,每個引腳允許通過的最大電流為35mA 整個芯片允許通過的最大電流為75mA。在我們設計相應的驅動電路時候,這些參數是相當重要的,而且是最容易被初學者所忽略的地方。同時在設計的時候,要留出一定量的余量出來,不能說單個引腳允許通過的電流為35mA,你就設計為35mA,這個時候你應該把設計的上限值定在20mA左右才能保證能夠穩定的工作。

(設計相應驅動電路時候,應該仔細閱讀芯片的數據手冊,了解每個引腳的驅動能力,以及整個芯片的驅動能力)

了解了相應的硬件后,我們再來編寫驅動程序。

首先定義LED的接口 #define LED P0 然后為亮滅常數定義一個宏,由硬件連接圖可以,當P0輸出為低電平時候LED亮,P0輸出為高電平時,LED熄滅。

#define LED_ON()LED = 0x00 //所有LED亮 #define LED_OFF()LED = 0xff //所有LED熄滅

下面到了重點了,究竟該如何釋放CPU,避免其做延時空等待這樣的事情呢。很簡單,我們為系統產生一個1MS的時標。假定LED需要亮500MS,熄滅500MS,那么我們可以對這個1MS的時標進行計數,當這個計數值達到500時候,清零該計數值,同時把LED的狀態改變。unsigned int g_u16LedTimeCount = 0;//LED計數器

unsigned char g_u8LedState = 0;//LED狀態標志, 0表示亮,1表示熄滅

void LedProcess(void){ if(0 == g_u8LedState)//如果LED的狀態為亮,則點亮LED { LED_ON();} else //否則熄滅LED { LED_OFF();} }

void LedStateChange(void){ if(g_bSystemTime1Ms)//系統1MS時標到 { g_bSystemTime1Ms = 0;g_u16LedTimeCount++;//LED計數器加一

if(g_u16LedTimeCount >= 500)//計數達到500,即500MS到了,改變LED的狀態。{ g_u16LedTimeCount = 0;g_u8LedState =!g_u8LedState;} } }

上面有一個變量沒有提到,就是g_bSystemTime1Ms。這個變量可以定義為位變量或者是其它變量,在我們的定時器中斷函數中對其置位,其它函數使用該變量后,應該對其復位(清0)。我們的主函數就可以寫成如下形式(示意代碼)void main(void){ while(1){ LedProcess();LedStateChange();} }

因為LED的亮或者滅依賴于LED狀態變量(g_u8LedState)的改變,而狀態變量的改變,又依賴于LED計數器的計數值(g_u16LedTimeCount,只有計數值達到一定后,狀態變量才改變)所以,兩個函數都沒有堵塞CPU的地方。讓我們來從頭到尾分析一遍整個程序的流程。

程序首先執行LedProcess();函數

因為g_u8LedState 的初始值為0(見定義,對于全局變量,在定義的時候最好給其一個確定的值)所以LED被點亮,然后退出LedStateChange()函數,執行下一個函數LedStateChange()在函數LedStateChange()內部首先判斷1MS的系統時標是否到了,如果沒有到就直接退出函數,如果到了,就把時標清0以便下一個時標消息的到來,同時對LED計數器加一,然后再判斷LED計數器是否到達我們預先想要的值500,如果沒有,則退出函數,如果有,對計數器清0,以便下次重新計數,同時把LED狀態變量取反,然后退出函數。

由上面整個流程可以知道,CPU所做的事情,就是對一些計數器加一,然后根據條件改變狀態,再根據這個狀態來決定是否點亮LED。這些函數執行所花的時間都是相當短的,如果主程序中還有其它函數,則CPU會順次往下執行下去。對于其它的函數(如果有的話)也要采取同樣的措施,保證其不堵塞CPU,如果全部基于這種方法設計,那么對于不是非常龐大的系統,我們的系統依舊可以保證多個任務(多個函數)同時執行。系統的實時性得到了一定的保證,從宏觀上看來,就是多個任務并發執行。

好了,這一章就到此為止,讓我們總結一下,究竟有哪些需要注意的吧。

(1)無論什么時候我們都要以實際應用的角度去考慮程序的編寫。

(2)無論什么時候都不要讓CPU白白浪費等待,尤其是延時(超過1MS)這樣的地方。(3)設計相應驅動電路時候,應該仔細閱讀芯片的數據手冊,了解每個引腳的驅動能力,以及整個芯片的驅動能力

(4)最重要的是,如何去釋放CPU(參考本章的例子),這是寫出合格程序的基礎。

附完整程序代碼(基于電子工程師之家的單片機開發板)

#include

sbit LED_SEG = P1^4;//數碼管段選 sbit LED_DIG = P1^5;//數碼管位選 sbit LED_CS11 = P1^6;//led控制位 sbit ir=P1^7;#define LED P0 //定義LED接口

bit g_bSystemTime1Ms = 0;// 1MS系統時標 unsigned int g_u16LedTimeCount = 0;//LED計數器

unsigned char g_u8LedState = 0;//LED狀態標志, 0表示亮,1表示熄滅

#define LED_ON()LED = 0x00;//所有LED亮 #define LED_OFF()LED = 0xff;//所有LED熄滅

void Timer0Init(void){ TMOD &= 0xf0;TMOD |= 0x01;//定時器0工作方式1 TH0 = 0xfc;//定時器初始值 TL0 = 0x66;TR0 = 1;ET0 = 1;} void LedProcess(void){ if(0 == g_u8LedState)//如果LED的狀態為亮,則點亮LED { LED_ON();} else //否則熄滅LED { LED_OFF();} }

void LedStateChange(void){ if(g_bSystemTime1Ms)//系統1MS時標到 { g_bSystemTime1Ms = 0;g_u16LedTimeCount++;//LED計數器加一

if(g_u16LedTimeCount >= 500)//計數達到500,即500MS到了,改變LED的狀態。{ g_u16LedTimeCount = 0;g_u8LedState =!g_u8LedState;} } }

void main(void){ Timer0Init();EA = 1;LED_CS11 = 1;//74HC595輸出允許

LED_SEG = 0;//數碼管段選和位選禁止(因為它們和LED共用P0口)LED_DIG = 0;while(1){ LedProcess();LedStateChange();} }

void Time0Isr(void)interrupt 1 { TH0 = 0xfc;//定時器重新賦初值 TL0 = 0x66;g_bSystemTime1Ms = 1;//1MS時標標志位置位 }

“從單片機初學者邁向單片機工程師”

第三章----模塊化編程初識

好的開始是成功的一半

通過上一章的學習,我想你已經掌握了如何在程序中釋放CPU了。希望能夠繼續堅持下去。一個良好的開始是成功的一半。我們今天所做的一切都是為了在單片機編程上做的更好。

在談論今天的主題之前,先說下我以前的一些經歷。在剛開始接觸到C語言程序的時候,由于學習內容所限,寫的程序都不是很大,一般也就幾百行而矣。所以所有的程序都完成在一個源文件里面。記得那時候大一參加學校里的一個電子設計大賽,調試了一個多星期,所有程序加起來大概將近1000行,長長的一個文件,從上瀏覽下來都要好半天。出了錯誤簡單的語法錯誤還好定位,其它一些錯誤,往往找半天才找的到。那個時候開始知道了模塊化編程這個東西,也嘗試著開始把程序分模塊編寫。最開始是把相同功能的一些函數(譬如1602液晶的驅動)全部寫在一個頭文件(.h)文件里面,然后需要調用的地方包含進去,但是很快發現這種方法有其局限性,很容易犯重復包含的錯誤。

而且調用起來也很不方便。很快暑假的電子設計大賽來臨了,學校對我們的單片機軟件編程進行了一些培訓。由于學校歷年來參加國賽和省賽,因此積累了一定數量的驅動模塊,那些日子,老師每天都會布置一定量的任務,讓我們用這些模塊組合起來,完成一定功能。而正是那些日子模塊化編程的培訓,使我對于模塊化編程有了更進一步的認識。并且程序規范也開始慢慢注意起來。此后的日子,無論程序的大小,均采用模塊化編程的方式去編寫。很長一段時間以來,一直有單片機愛好者在QQ上和我一起交流。有時候,他們會發過來一些有問題的程序源文件,讓我幫忙修改一下。同樣是長長的一個文件,而且命名極不規范,從頭看下來,著實是痛苦,說實話,還真不如我重新給他們寫一個更快一些,此話到不假,因為手頭積累了一定量的模塊,在完成一個新的系統時候,只需要根據上層功能需求,在底層模塊的支持下,可以很快方便的完成。而不需要從頭到尾再一磚一瓦的重新編寫。藉此,也可以看出模塊化編程的一個好處,就是可重復利用率高。下面讓我們揭開模塊化神秘面紗,一窺其真面目。C語言源文件 *.c 提到C語言源文件,大家都不會陌生。因為我們平常寫的程序代碼幾乎都在這個XX.C文件里面。編譯器也是以此文件來進行編譯并生成相應的目標文件。作為模塊化編程的組成基礎,我們所要實現的所有功能的源代碼均在這個文件里。理想的模塊化應該可以看成是一個黑盒子。即我們只關心模塊提供的功能,而不管模塊內部的實現細節。好比我們買了一部手機,我們只需要會用手機提供的功能即可,不需要知曉它是如何把短信發出去的,如何響應我們按鍵的輸入,這些過程對我們用戶而言,就是是一個黑盒子。

在大規模程序開發中,一個程序由很多個模塊組成,很可能,這些模塊的編寫任務被分配到不同的人。而你在編寫這個模塊的時候很可能就需要利用到別人寫好的模塊的借口,這個時候我們關心的是,它的模塊實現了什么樣的接口,我該如何去調用,至于模塊內部是如何組織的,對于我而言,無需過多關注。而追求接口的單一性,把不需要的細節盡可能對外部屏蔽起來,正是我們所需要注意的地方。C語言頭文件 *.h 談及到模塊化編程,必然會涉及到多文件編譯,也就是工程編譯。在這樣的一個系統中,往往會有多個C文件,而且每個C文件的作用不盡相同。在我們的C文件中,由于需要對外提供接口,因此必須有一些函數或者是變量提供給外部其它文件進行調用。假設我們有一個LCD.C文件,其提供最基本的LCD的驅動函數 LcdPutChar(char cNewValue);//在當前位置輸出一個字符 而在我們的另外一個文件中需要調用此函數,那么我們該如何做呢?

頭文件的作用正是在此。可以稱其為一份接口描述文件。其文件內部不應該包含任何實質性的函數代碼。我們可以把這個頭文件理解成為一份說明書,說明的內容就是我們的模塊對外提供的接口函數或者是接口變量。同時該文件也包含了一些很重要的宏定義以及一些結構體的信息,離開了這些信息,很可能就無法正常使用接口函數或者是接口變量。但是總的原則是:不該讓外界知道的信息就不應該出現在頭文件里,而外界調用模塊內接口函數或者是接口變量所必須的信息就一定要出現在頭文件里,否則,外界就無法正確的調用我們提供的接口功能。因而為了讓外部函數或者文件調用我們提供的接口功能,就必須包含我們提供的這個接口描述文件----即頭文件。同時,我們自身模塊也需要包含這份模塊頭文件(因為其包含了模塊源文件中所需要的宏定義或者是結構體),好比我們平常所用的文件都是一式三份一樣,模塊本身也需要包含這個頭文件。

下面我們來定義這個頭文件,一般來說,頭文件的名字應該與源文件的名字保持一致,這樣我們便可以清晰的知道哪個頭文件是哪個源文件的描述。

于是便得到了LCD.C的頭文件LCD.h 其內容如下。#ifndef _LCD_H_ #define _LCD_H_ extern LcdPutChar(char cNewValue);#endif

這與我們在源文件中定義函數時有點類似。不同的是,在其前面添加了extern 修飾符表明其是一個外部函數,可以被外部其它模塊進行調用。#ifndef _LCD_H_ #define _LCD_H_ #endif

這個幾條條件編譯和宏定義是為了防止重復包含。假如有兩個不同源文件需要調用LcdPutChar(char cNewValue)這個函數,他們分別都通過#include “Lcd.h”把這個頭文件包含了進去。在第一個源文件進行編譯時候,由于沒有定義過 _LCD_H_ 因此 #ifndef _LCD_H_ 條件成立,于是定義_LCD_H_ 并將下面的聲明包含進去。在第二個文件編譯時候,由于第一個文件包含時候,已經將_LCD_H_定義過了。因此#ifndef _LCD_H_ 不成立,整個頭文件內容就沒有被包含。假設沒有這樣的條件編譯語句,那么兩個文件都包含了extern LcdPutChar(char cNewValue);就會引起重復包含的錯誤。

不得不說的typedef 很多朋友似乎了習慣程序中利用如下語句來對數據類型進行定義 #define uint unsigned int #define uchar unsigned char 然后在定義變量的時候 直接這樣使用 uint g_nTimeCounter = 0;不可否認,這樣確實很方便,而且對于移植起來也有一定的方便性。但是考慮下面這種情況你還會 這么認為嗎?

#define PINT unsigned int * //定義unsigned int 指針類型 PINT g_npTimeCounter, g_npTimeState;那么你到底是定義了兩個unsigned int 型的指針變量,還是一個指針變量,一個整形變量呢?而你的初衷又是什么呢,想定義兩個unsigned int 型的指針變量嗎?如果是這樣,那么估計過不久就會到處抓狂找錯誤了。

慶幸的是C語言已經為我們考慮到了這一點。typedef 正是為此而生。為了給變量起一個別名我們可以用如下的語句

typedef unsigned int uint16;//給指向無符號整形變量起一個別名 uint16 typedef unsigned int * puint16;//給指向無符號整形變量指針起一個別名 puint16 在我們定義變量時候便可以這樣定義了:

uint16 g_nTimeCounter = 0;//定義一個無符號的整形變量 puint16 g_npTimeCounter;//定義一個無符號的整形變量的指針

在我們使用51單片機的C語言編程的時候,整形變量的范圍是16位,而在基于32的微處理下的整形變量是32位。倘若我們在8位單片機下編寫的一些代碼想要移植到32位的處理器上,那么很可能我們就需要在源文件中到處修改變量的類型定義。這是一件龐大的工作,為了考慮程序的可移植性,在一開始,我們就應該養成良好的習慣,用變量的別名進行定義。如在8位單片機的平臺下,有如下一個變量定義 uint16 g_nTimeCounter = 0;如果移植32單片機的平臺下,想要其的范圍依舊為16位。

可以直接修改uint16 的定義,即

typedef unsigned short int uint16;這樣就可以了,而不需要到源文件處處尋找并修改。

將常用的數據類型全部采用此種方法定義,形成一個頭文件,便于我們以后編程直接調用。文件名 MacroAndConst.h 其內容如下:

#ifndef _MACRO_AND_CONST_H_ #define _MACRO_AND_CONST_H_

typedef unsigned int uint16;typedef unsigned int UINT;typedef unsigned int uint;typedef unsigned int UINT16;typedef unsigned int WORD;typedef unsigned int word;typedef int int16;typedef int INT16;typedef unsigned long uint32;

typedef unsigned long UINT32;typedef unsigned long DWORD;typedef unsigned long dword;typedef long int32;typedef long INT32;typedef signed char int8;typedef signed char INT8;typedef unsigned char byte;typedef unsigned char BYTE;typedef unsigned char uchar;typedef unsigned char UINT8;typedef unsigned char uint8;typedef unsigned char BOOL;#endif

至此,似乎我們對于源文件和頭文件的分工以及模塊化編程有那么一點概念了。那么讓我們趁熱打鐵,將上一章的我們編寫的LED閃爍函數進行模塊劃分并重新組織進行編譯。

在上一章中我們主要完成的功能是P0口所驅動的LED以1Hz的頻率閃爍。其中用到了定時器,以及LED驅動模塊。因而我們可以簡單的將整個工程分成三個模塊,定時器模塊,LED模塊,以及主函數 對應的文件關系如下

main.c Timer.h?Timer.c--Led.h?Led.c--在開始重新編寫我們的程序之前,先給大家講一下如何在KEIL中建立工程模板吧,這個模板是我一直沿用至今。希望能夠給大家一點啟發。

下面的內容就主要以圖片為主了。同時輔以少量文字說明。我們以芯片AT89S52為例。

(原文件名:1.jpg)

引用圖片

(原文件名:2.jpg)

引用圖片

(原文件名:3.jpg)

引用圖片

(原文件名:4.jpg)

引用圖片

(原文件名:5.jpg)

引用圖片

(原文件名:6.jpg)

引用圖片

(原文件名:7.jpg)

引用圖片

(原文件名:8.jpg)

引用圖片

(原文件名:9.jpg)

引用圖片

(原文件名:10.jpg)

引用圖片

(原文件名:11.jpg)

引用圖片

(原文件名:12.jpg)

引用圖片

(原文件名:13.jpg)

引用圖片

(原文件名:14.jpg)

引用圖片

(原文件名:15.jpg)

引用圖片

(原文件名:16.jpg)

引用圖片

(原文件名:17.jpg)

引用圖片

(原文件名:18.jpg)

引用圖片

(原文件名:19.jpg)

引用圖片

(原文件名:20.jpg)

引用圖片

(原文件名:21.jpg)

引用圖片

(原文件名:22.jpg)

引用圖片

OK,到此一個簡單的工程模板就建立起來了,以后我們再新建源文件和頭文件的時候,就可以直接保存到src文件目錄下面了。

下面我們開始編寫各個模塊文件。

首先編寫Timer.c 這個文件主要內容就是定時器初始化,以及定時器中斷服務函數。其內容如下。#include

bit g_bSystemTime1Ms = 0;// 1MS系統時標

void Timer0Init(void){ TMOD &= 0xf0;TMOD |= 0x01;//定時器0工作方式1 TH0 = 0xfc;//定時器初始值 TL0 = 0x66;TR0 = 1;ET0 = 1;}

void Time0Isr(void)interrupt 1 { TH0 = 0xfc;//定時器重新賦初值 TL0 = 0x66;g_bSystemTime1Ms = 1;//1MS時標標志位置位 }

由于在Led.c文件中需要調用我們的g_bSystemTime1Ms變量。同時主函數需要調用Timer0Init()初始化函數,所以應該對這個變量和函數在頭文件里作外部聲明。以方便其它函數調用。

Timer.h 內容如下。#ifndef _TIMER_H_ #define _TIMER_H_

extern void Timer0Init(void);extern bit g_bSystemTime1Ms;#endif

完成了定時器模塊后,我們開始編寫LED驅動模塊。Led.c 內容如下:

#include #include “MacroAndConst.h” #include “Led.h” #include “Timer.h”

static uint16 g_u16LedTimeCount = 0;//LED計數器 static uint8 g_u8LedState = 0;//LED狀態標志, 0表示亮,1表示熄滅

#define LED P0 //定義LED接口

#define LED_ON()LED = 0x00;//所有LED亮 #define LED_OFF()LED = 0xff;//所有LED熄滅

void LedProcess(void){ if(0 == g_u8LedState)//如果LED的狀態為亮,則點亮LED { LED_ON();} else //否則熄滅LED { LED_OFF();} }

void LedStateChange(void){ if(g_bSystemTime1Ms)//系統1MS時標到 { g_bSystemTime1Ms = 0;g_u16LedTimeCount++;//LED計數器加一

if(g_u16LedTimeCount >= 500)//計數達到500,即500MS到了,改變LED的狀態。{ g_u16LedTimeCount = 0;g_u8LedState =!g_u8LedState;} } }

這個模塊對外的借口只有兩個函數,因此在相應的Led.h 中需要作相應的聲明。Led.h 內容: #ifndef _LED_H_ #define _LED_H_

extern void LedProcess(void);extern void LedStateChange(void);#endif

這兩個模塊完成后,我們將其C文件添加到工程中。然后開始編寫主函數里的代碼。如下所示:

#include #include “MacroAndConst.h” #include “Timer.h” #include “Led.h”

sbit LED_SEG = P1^4;//數碼管段選 sbit LED_DIG = P1^5;//數碼管位選 sbit LED_CS11 = P1^6;//led控制位

void main(void){ LED_CS11 = 1;//74HC595輸出允許

LED_SEG = 0;//數碼管段選和位選禁止(因為它們和LED共用P0口)LED_DIG = 0;Timer0Init();EA = 1;while(1){ LedProcess();LedStateChange();} }

整個工程截圖如下:

至此,第三章到此結束。

一起來總結一下我們需要注意的地方吧

[color=#FF0000]1.C語言源文件(*.c)的作用是什么 2.C語言頭文件(*.h)的作用是什么 3.typedef 的作用 4.工程模板如何組織

5.如何創建一個多模塊(多文件)的工程

“從單片機初學者邁向單片機工程師”之KEY主題討論

按鍵程序編寫的基礎

從這一章開始,我們步入按鍵程序設計的殿堂。在基于單片機為核心構成的應用系統中,用戶輸入是必不可少的一部分。輸入可以分很多種情況,譬如有的系統支持PS2鍵盤的接口,有的系統輸入是基于編碼器,有的系統輸入是基于串口或者USB或者其它輸入通道等等。在各種輸入途徑中,更常見的是,基于單個按鍵或者由單個鍵盤按照一定排列構成的矩陣鍵盤(行列鍵盤)。我們這一篇章主要討論的對象就是基于單個按鍵的程序設計,以及矩陣鍵盤的程序編寫。◎按鍵檢測的原理

常見的獨立按鍵的外觀如下,相信大家并不陌生,各種常見的開發板學習板上隨處可以看到他們的身影。

(原文件名:1.jpg)

引用圖片

總共有四個引腳,一般情況下,處于同一邊的兩個引腳內部是連接在一起的,如何分辨兩個引腳是否處在同一邊呢?可以將按鍵翻轉過來,處于同一邊的兩個引腳,有一條突起的線將他們連接一起,以標示它們倆是相連的。如果無法觀察得到,用數字萬用表的二極管擋位檢測一下即可。搞清楚這點非常重要,對于我們畫PCB的時候的封裝很有益。

它們和我們的單片機系統的I/O口連接一般如下:

(原文件名:2.jpg)

引用圖片

對于單片機I/O內部有上拉電阻的微控制器而言,還可以省掉外部的那個上拉電阻。簡單分析一下按鍵檢測的原理。當按鍵沒有按下的時候,單片機I/O通過上拉電阻R接到VCC,我們在程序中讀取該I/O的電平的時候,其值為1(高電平);當按鍵S按下的時候,該I/O被短接到GND,在程序中讀取該I/O的電平的時候,其值為0(低電平)。這樣,按鍵的按下與否,就和與該按鍵相連的I/O的電平的變化相對應起來。結論:我們在程序中通過檢測到該I/O口電平的變化與否,即可以知道按鍵是否被按下,從而做出相應的響應。一切看起來很美好,是這樣的嗎?

◎現實并非理想

在我們通過上面的按鍵檢測原理得出上述的結論的時候,其實忽略了一個重要的問題,那就是現實中按鍵按下時候的電平變化狀態。我們的結論是基于理想的情況得出來的,就如同下面這幅按鍵按下時候對應電平變化的波形圖一樣:

(原文件名:3.jpg)

引用圖片

而實際中,由于按鍵的彈片接觸的時候,并不是一接觸就緊緊的閉合,它還存在一定的抖動,盡管這個時間非常的短暫,但是對于我們執行時間以us為計算單位的微控制器來說,它太漫長了。因而,實際的波形圖應該如下面這幅示意圖一樣。

(原文件名:4.jpg)

引用圖片

這樣便存在這樣一個問題。假設我們的系統有這樣功能需求:在檢測到按鍵按下的時候,將某個I/O的狀態取反。由于這種抖動的存在,使得我們的微控制器誤以為是多次按鍵的按下,從而將某個I/O的狀態不斷取反,這并不是我們想要的效果,假如該I/O控制著系統中某個重要的執行的部件,那結果更不是我們所期待的。于是乎有人便提出了軟件消除抖動的思想,道理很簡單:抖動的時間長度是一定的,只要我們避開這段抖動時期,檢測穩定的時候的電平不久可以了嗎?聽起來確實不錯,而且實際應用起來效果也還可以。于是,各種各樣的書籍中,在提到按鍵檢測的時候,總也不忘說道軟件消抖。就像下面的偽代碼所描述的一樣。(假設按鍵按下時候,低電平有效)

If(0 == io_KeyEnter)//如果有鍵按下了 { Delayms(20);//先延時20ms避開抖動時期

If(0 == io_KeyEnter)//然后再檢測,如果還是檢測到有鍵按下 { return KeyValue;//是真的按下了,返回鍵值 } else { return KEY_NULL //是抖動,返回空的鍵值 } while(0 == io_KeyEnter);//等待按鍵釋放 }

所以合理的分配好微控制的處理時間,是編寫按鍵程序的基礎。?乍看上去,確實挺不錯,實際中呢?在實際的系統中,一般是不允許這么樣做的。為什么呢?首先,這里的Delayms(20), 讓微控制器在這里白白等待了20 ms 的時間,啥也沒干,考慮我在《學會釋放CPU》一章中所提及的幾點,這是不可取的。其次while(0 == io_KeyEnter);更是程序設計中的大忌(極少的特殊情況例外)。任何非極端情況下,都不要使用這樣語句來堵塞微控制器的執行進程。原本是等待按鍵釋放,結果CPU就一直死死的盯住該按鍵,其它事情都不管了,那其它事情不干了嗎?你同意別人可不會同意

◎消除抖動有必要嗎? 的確,軟件上的消抖確實可以保證按鍵的有效檢測。但是,這種消抖確實有必要嗎?有人提出了這樣的疑問。抖動是按鍵按下的過程中產生的,如果按鍵沒有按下,抖動會產生嗎?如果沒有按鍵按下,抖動也會在I/O上出現,我會立刻把這個微控制器錘了,永遠不用這樣一款微控制器。所以抖動的出現即意味著按鍵已經按下,盡管這個電平還沒有穩定。所以只要我們檢測到按鍵按下,即可以返回鍵值,問題的關鍵是,在你執行完其它任務的時候,再次執行我們的按鍵任務的時候,抖動過程還沒有結束,這樣便有可能造成重復檢測。所以,如何在返回鍵值后,避免重復檢測,或者在按鍵一按下就執行功能函數,當功能函數的執行時間小于抖動時間時候,如何避免再次執行功能函數,就成為我們要考慮的問題了。這是一個仁者見仁,智者見智的問題,就留給大家去思考吧。所以消除抖動的目的是:防止按鍵一次按下,多次響應。

“從單片機初學者邁向單片機工程師”之KEY主題討論

基于狀態轉移的獨立按鍵程序設計)的那種,有一個小液晶屏,還有四個按鍵,功能是時鐘,鬧鐘以及秒表。在調整時間的時候,短按+鍵每次調整值加一,長按的時候調整值連續增加。小的時候很好奇,這樣的功能到底是如何實現的呢,今天就讓我們來剖析它的原理吧。? 本章所描述的按鍵程序要達到的目的:檢測按鍵按下,短按,長按,釋放。即通過按鍵的返回值我們可以獲取到如下的信息:按鍵按下(短按),按鍵長按,按鍵連_發,按鍵釋放。不知道大家還記得小時候玩過的電子鐘沒有,就是外形類似于CALL 機(CALL 機,好像是很古老的東西了 狀態在生活中隨處可見。譬如早上的時候,鬧鐘把你叫醒了,這個時候,你便處于清醒的狀態,馬上你就穿衣起床洗漱吃早餐,這一系列事情就是你在這個狀態做的事情。做完這些后你會去等車或者開車去上班,這個時候你就處在上班途中的狀態?..中午下班時間到了,你就處于中午下班的狀態,諸如此類等等,在每一個狀態我們都會做一些不同的事情,而總會有外界條件促使我們轉換到另外一種狀態,譬如鬧鐘叫醒我們了,下班時間到了等等。對于狀態的定義出發點不同,考慮的方向不同,或者會有些許細節上面的差異,但是大的狀態總是相同的。生活中的事物同樣遵循同樣的規律,譬如,用一個智能充電器給你的手機電池充電,剛開始,它是處于快速充電狀態,隨著電量的增加,電壓的升高,當達到規定的電壓時候,它會轉換到恒壓充電。總而言之,細心觀察,你會發現生活中的總總都可以歸結為一個個的狀態,而狀態的變換或者轉移總是由某些條件引起同時伴隨著一些動作的發生。我們的按鍵亦遵循同樣的規律,下面讓我們來簡單的描繪一下它的狀態流程轉移圖。

(原文件名:1.jpg)

引用圖片

下面對上面的流程圖進行簡要的分析。首先按鍵程序進入初始狀態S1,在這個狀態下,檢測按鍵是否按下,如果有按下,則進入按鍵消抖狀態2,在下一次執行按鍵程序時候,直接由按鍵消抖狀態進入按鍵按下狀態3,在此狀態下檢測按鍵是否按下,如果沒有按鍵按下,則返回初始狀態S1,如果有則可以返回鍵值,同時進入長按狀態S4,在長按狀態下每次進入按鍵程序時候對按鍵時間計數,當計數值超過設定閾值時候,則表明長按事件發生,同時進入按鍵連_發狀態S5。如果按鍵鍵值為空鍵,則返回按鍵釋放狀態S6,否則繼續停留在本狀態。在按鍵連_發狀態下,如果按鍵鍵值為空鍵則返回按鍵釋放狀態S6,如果按鍵時間計數超過連_發閾值,則返回連_發按鍵值,清零時間計數后繼續停留在本狀態。

看了這么多,也許你已經有一個模糊的概念了,下面讓我們趁熱打鐵,一起來動手編寫按鍵驅動程序吧。

下面是我使用的硬件的連接圖。

(原文件名:2.jpg)

引用圖片

硬件連接很簡單,四個獨立按鍵分別接在P3^0------P3^3四個I/O上面。

因為51單片機I/O口內部結構的限制,在讀取外部引腳狀態的時候,需要向端口寫1.在51單片機復位后,不需要進行此操作也可以進行讀取外部引腳的操作。因此,在按鍵的端口沒有復用的情況下,可以省略此步驟。而對于其它一些真正雙向I/O口的單片機來說,將引腳設置成輸入狀態,是必不可少的一個步驟。下面的程序代碼初始化引腳為輸入。void KeyInit(void){ io_key_1 = 1;io_key_2 = 1;io_key_3 = 1;io_key_4 = 1;} 根據按鍵硬件連接定義按鍵鍵值

#define KEY_VALUE_1 0x0e #define KEY_VALUE_2 0x0d #define KEY_VALUE_3 0x0b #define KEY_VALUE_4 0x07 #define KEY_NULL 0x0f 下面我們來編寫按鍵的硬件驅動程序。

根據第一章所描述的按鍵檢測原理,我們可以很容易的得出如下的代碼: static uint8 KeyScan(void){ if(io_key_1 == 0)return KEY_VALUE_1;if(io_key_2 == 0)return KEY_VALUE_2;if(io_key_3 == 0)return KEY_VALUE_3;if(io_key_4 == 0)return KEY_VALUE_4;return KEY_NULL;} 其中io_key_1等是我們按鍵端口的定義,如下所示: sbit io_key_1 = P3^0;sbit io_key_2 = P3^1;sbit io_key_3 = P3^2;sbit io_key_4 = P3^3;

KeyScan()作為底層按鍵的驅動程序,為上層按鍵掃描提供一個接口,這樣我們編寫的上層按鍵掃描函數可以幾乎不用修改就可以拿到我們的其它程序中去使用,使得程序復用性大大提高。同時,通過有意識的將與底層硬件連接緊密的程序和與硬件無關的代碼分開寫,使得程序結構層次清晰,可移植性也更好。對于單片機類的程序而言,能夠做到函數級別的代碼重用已經足夠了。在編寫我們的上層按鍵掃描函數之前,需要先完成一些宏定義。//定義長按鍵的TICK數,以及連_發間隔的TICK數 #define KEY_LONG_PERIOD 100 #define KEY_CONTINUE_PERIOD 25

//定義按鍵返回值狀態(按下,長按,連_發,釋放)#define KEY_DOWN 0x80 #define KEY_LONG 0x40 #define KEY_CONTINUE 0x20 #define KEY_UP 0x10

//定義按鍵狀態

#define KEY_STATE_INIT 0 #define KEY_STATE_WOBBLE 1 #define KEY_STATE_PRESS 2 #define KEY_STATE_LONG 3 #define KEY_STATE_CONTINUE 4 #define KEY_STATE_RELEASE 5

接著我們開始編寫完整的上層按鍵掃描函數,按鍵的短按,長按,連按,釋放等等狀態的判斷均是在此函數中完成。對照狀態流程轉移圖,然后再看下面的函數代碼,可以更容易的去理解函數的執行流程。完整的函數代碼如下: void GetKey(uint8 *pKeyValue){ static uint8 s_u8KeyState = KEY_STATE_INIT;static uint8 s_u8KeyTimeCount = 0;static uint8 s_u8LastKey = KEY_NULL;//保存按鍵釋放時候的鍵值 uint8 KeyTemp = KEY_NULL;

KeyTemp = KeyScan();//獲取鍵值

switch(s_u8KeyState){ case KEY_STATE_INIT : { if(KEY_NULL!=(KeyTemp)){ s_u8KeyState = KEY_STATE_WOBBLE;} } break;

case KEY_STATE_WOBBLE : //消抖 { s_u8KeyState = KEY_STATE_PRESS;} break;

case KEY_STATE_PRESS : { if(KEY_NULL!=(KeyTemp)){ s_u8LastKey = KeyTemp;//保存鍵值,以便在釋放按鍵狀態返回鍵值 KeyTemp |= KEY_DOWN;//按鍵按下 s_u8KeyState = KEY_STATE_LONG;} else { s_u8KeyState = KEY_STATE_INIT;} } break;

case KEY_STATE_LONG : { if(KEY_NULL!=(KeyTemp)){ if(++s_u8KeyTimeCount > KEY_LONG_PERIOD){ s_u8KeyTimeCount = 0;KeyTemp |= KEY_LONG;//長按鍵事件發生 s_u8KeyState = KEY_STATE_CONTINUE;} } else { s_u8KeyState = KEY_STATE_RELEASE;} } break;

case KEY_STATE_CONTINUE : { if(KEY_NULL!=(KeyTemp)){ if(++s_u8KeyTimeCount > KEY_CONTINUE_PERIOD){ s_u8KeyTimeCount = 0;KeyTemp |= KEY_CONTINUE;} } else { s_u8KeyState = KEY_STATE_RELEASE;} } break;

case KEY_STATE_RELEASE : { s_u8LastKey |= KEY_UP;KeyTemp = s_u8LastKey;s_u8KeyState = KEY_STATE_INIT;} break;

default : break;} *pKeyValue = KeyTemp;//返回鍵值 } 關于這個函數內部的細節我并不打算花過多筆墨去講解。對照著按鍵狀態流程轉移圖,然后去看程序代碼,你會發現其實思路非常清晰。最能讓人理解透徹的,莫非就是將整個程序自己看懂,然后想象為什么這個地方要這樣寫,抱著思考的態度去閱讀程序,你會發現自己的程序水平會慢慢的提高。所以我更希望的是你能夠認認真真的看完,然后思考。也許你會收獲更多。

不管怎么樣,這樣的一個程序已經完成了本章開始時候要求的功能:按下,長按,連按,釋放。事實上,如果掌握了這種基于狀態轉移的思想,你會發現要求實現其它按鍵功能,譬如,多鍵按下,功能鍵等等,亦相當簡單,在下一章,我們就去實現它。

在主程序中我編寫了這樣的一段代碼,來演示我實現的按鍵功能。void main(void){ uint8 KeyValue = KEY_NULL;uint8 temp = 0;LED_CS11 = 1;//流水燈輸出允許 LED_SEG = 0;LED_DIG = 0;Timer0Init();KeyInit();EA = 1;while(1){ Timer0MainLoop();KeyMainLoop(&KeyValue);

if(KeyValue ==(KEY_VALUE_1 | KEY_DOWN))P0 = ~1;if(KeyValue ==(KEY_VALUE_1 | KEY_LONG))P0 = ~2;if(KeyValue ==(KEY_VALUE_1 | KEY_CONTINUE)){ P0 ^= 0xf0;} if(KeyValue ==(KEY_VALUE_1 | KEY_UP))P0 = 0xa5;} } 按住第一個鍵,可以清晰的看到P0口所接的LED的狀態的變化。當按鍵按下時候,第一個LED燈亮,等待2 S后第二個LED亮,第一個熄滅,表示長按事件發生。再過500 ms 第5~8個LED閃爍,表示連按事件發生。當釋放按鍵時候,P0口所接的LED的狀態為: 滅亮滅亮亮滅亮滅,這也正是P0 = 0xa5這條語句的功能。

第三篇:C語言學習心得

C語言學習心得體會

在科技高度發展的今天,計算機在人們生活、學習和工作中的作用越來越突出。我們都知道C語言是一種計算機語言,而作為計算機專業的我們學習它,就更有助于我們更好的了解計算機,與計算機進行交流,因此,C語言的學習對我們尤其重要。

說實話這個學期剛開始學C語言的時候,很感覺迷茫,對里面的好多東西很陌生,在操作運用的時候感到很棘手,畢竟,萬事開頭難嘛。在此之前從沒有接觸過C語言,有點摸不著頭腦。可是在上機過后,我覺得編程是很有趣的一件事,哪怕你編出的只是一個很簡單的程序都會讓你很有成就感。我知道要學好C語言不容易,可是我決定完成這件不容易的事。

在課堂上老師從最基本的跟我們講起,要學好C語言就必須要先懂得最基本的語法知識,看課本是必需的。我覺得看不懂也沒關系,盡力去理解就好了,在對知識有了一個大致的了解過后,就要上機實踐。學習C語言一定要動手,只看不做,眼高手低是不行的。

最開始我們打書上的例題,熟悉程序,慢慢的開始試著編程。老師說過在編程時要理清自己的思路,然后再轉換成C語言中的語言,這個時候就更要動手了,只有通過上機操作才能驗證自己程序的正確性。執行程序,不要害怕錯誤,其實,我覺得錯誤是好的,知道了自己所學知識的不足,并根據提示改正程序中發生的錯誤,一種成就感油然而生,覺得自己的付出都是值得的。

我覺得良好的編程習慣是學好C語言的重要因素,只有勤動手,多動腦才能學好C語言,光說不練是不行的。在學習的時候,不會的一定要問明白,可以求助于老師,同學,不要自己一個人鉆牛角尖,既浪費時間又學不到東西。

上課的時候也一定要認真聽,老師講的肯定是最重要的,錯過了就是一大筆損失,認真聽講才可以提高學習效率嘛。另外我覺得在編程之前,要把自己的想法寫在紙上,如果是簡單一點的程序不需要這樣,如果程序比較復雜,就寫下來,這樣可以讓思路更加清晰。輸入程序時一定要認真,不要把“,”與“;”混淆,用scanf的時候不要忘記“&”,用“switch”要記得“break”,用if,while的時候注意不要加“;”,“{}”“()”一定要配對,不要多也不要少一半,“=”與“==”的區別要清楚,要勤查優先級,要記住一些基本的,例如兩個值之間的調換怎么寫等等。

學習C語言需要的是堅持下去的毅力和認真對待每次錯誤的耐心,還有孜孜不倦的努力。擁有一個良好的心態,相信自己,你就會發現學好C語言不再困難!

第四篇:c語言學習心得

導語:c語言是一個有序的學習,學了最基本的替換,然后擴展到循環,嵌套,條理很清楚,不是一個零散的知識,實際上所有的課程都如此,不過通過實訓我也知道了自己的不足,存在的很多問題。

c語言學習心得

首先我要告訴大家的是:第一,學習無捷徑!對于學習編程而言,你現在的付出將來都是有回報的。但是,學習C語言也需要方法。

我遇到過很多學習C語言的人,包括我以前的同學,很多人都是學到一半就放棄了。那么為什么那么多人學習C語言都半途而廢呢?原因就是他們找不到正確的學習方法!在學習的過程中四處碰壁,興趣和自信心逐漸被消耗殆盡。對他們來說學習C語言是一件很痛苦的事!

事實上學習編程是一件很好玩、很有趣、很有意思也很有前途的事情!那么學習C語言有什么好的方法呢?根據我自己多年的總結,以及很多編程前輩的經驗,主要有以下幾個方面:

1)分清主次

學習C語言最忌諱的就是不分主次,這是絕大多數學習C語言的同學都會犯的錯誤!我們剛開始學習的時候只需要將那些最重要的、最核心的學會就已經很好了!先將最精髓的東西提煉出來,再將整個C語言學一遍,從全局上把握C語言。對于那些次要的,有需要再學,沒有需要也可以不學。

2)一定要多上機,多“敲”代碼

編程是一門實踐性的學科,絕對不是理論。如果不動手“敲”代碼的話,永遠都學不會編程。很多問題只有在“敲代碼”的時候才能發現,才會有更加深刻的體會、領悟和理解。而不是靠死記硬背書中的注意點,那樣真的很痛苦。我在學習編程的時候從來都不會刻意記憶什么注意點,這些知識點都是在不停“敲代碼”的過程中,自然而然地融入我的身體中的。你們一定要記住一句話:“程序是寫出來的,不是看書看出來的!”

3)要“敲代碼”,必學盲打

盲打是學習編程最基本的技能。就算你C語言學得很好,達到了“思想在鍵盤上飛舞”的境界,但是如果你不會盲打,那你想“飛”也“飛”不起來!所以,不會盲打會非常影響你的學習效率。

4)要學會記筆記

編程需要不斷地積累。我們一定要學會模仿別人優秀的代碼、優秀的算法,然后將它記下來。一定要站在巨人的肩膀上學習。但是我們的記憶能力是有限的,時間長了難免會遺忘,所以一定要學會記筆記。一有心得、體會、感悟就寫下來,這些都是很珍貴的。

我們在記筆記的時候,如果眼前沒有計算機則可以先寫在紙上,但事后一定要將它整理成電子版。整理成電子版看起來會很方便、舒適,還可以隨意地增添和刪改,保存時間也長。

c語言學習心得

說到我學習C語言時,真是用千言萬語呀!抄程序是最笨的方法但我認為它是進步最快的方法,抄程序是積累經驗的時候,而做項目才是真正把所學為所用的時候,可以說只有你做一個 大點的項目出來才能真正是說明你學到了東西,你會用所學的東西,要不然就算你學的再多,不會用也沒用。

做學問特別是計算機一定要做的精準,比如說一個語句一個關鍵 字,你一定要把它幾乎所有的用方法都能清楚明白,一句話要學精了,語法掌握住了,接下來就是寫程序了,其實抄程序并不是說一直沒有目的去抄,你會發現當你抄一段時間以后就不用再抄 了,因為大部分都是一樣的你一看就知道怎么寫了,當你一看到程序就知道它什么功能,那里有錯的時候,那你的成績可是進步不小啊,這并不需要太多的時間,只 要你用心一個月足夠了。

跟大家說幾點經驗:

1.在學習的時候一定要注意這幾點,不會的一定要問明白,不管誰能讓他教會你知識就是你的了,要學會讓知識為我所用。在看書的時候一定要做好標記,特別是不懂的地方一定要標明是什么意思。

2.在學習語言的時候一定要記住動手,不要只說不做,這樣會行成眼高手低,不管什么樣的程序都要親手做過才能說會了,不要整天說我不會學不會,其實 是你不想學,只是你下決心抄一個月程序,我保證我能有大的進步,其實當你抄到一周到兩周的時候你就會特想抄,因為你會發現程序你能看懂了,能幫別人調程序 了,有一種成就感呀!它會讓你更加努力的去學習。

3.再一點是我建議大家在上課的時候少看課本,課本要在下課的時候看特別是上課前一定要先看看課本,上課的時候呢就不要看了,不要老師講到那個問題 了你馬上在書上找,這樣不好,會影響你的注意力,其實還真不如注意聽老師講呢?因為你要是一邊聽一邊看課本,你是看到了書上的答案但是老師的思路你沒有聽 到,而要是你不看的話,你聽明白了思路,一定是想迫切的看到結果,這個時候看課本才是記的最死的時候,學習要的是就是個效率嗎?

4.提醒大家學習要講效率,我發現有很多同學天天學習,每天最早到教室,走的又最晚,別人玩他在學,別人學他也學,可是別的一天30%的學習時間卻 比他們一天50%以上的學習時間的效率要高上不僅僅是幾倍的問題,所以我要說的是不要對別人說你天天在學習,要說你天天在進步,學習不是要你學習了多久 是,是要你學了多少東西的,你學一小時還沒有別人學一分鐘的效率高,難道自己不是浪費時間嗎?不想學的時候就不要學,出去玩一會兒再來學說不定會有更好的 效果。希望這些經驗能跟大家分享一下,最后還是要跟大家強調一點,抄程序是學好C語言的最好最快的方法。

第五篇:第四章C語言學習心得

第四章C語言學習心得

2011/8/13 SHMILY

1、C語言邏輯值,非零表示”真”,零表示”假”

2、關系運算符和關系表達式:

小于 <

小于等于 <= 大于 >

大于等于 >= 等于 ==

不等于!= 有兩個字符組成的運算符之間不允許加空格 <=(正確)

< =(錯誤)關系運算符是雙目運算符,自左向右結合

前四種運算符(<、<=、>、>=)的優先級相同,后兩種運算符(==、!=)的優先級相同,前四種優先級高于后兩種優先級

3、優先級比較:算術運算符 > 關系運算符 > 賦值運算符

4、邏輯運算符和邏輯表達式:

&& “與”

|| ”或”

!“非” && 和 || 為雙目運算符,!為單目運算符

優先級比較 :!> 算術運算符 > 關系運算符 > && > || > 賦值運算符5、0 < x <10 的數學含義??

C語言中含義??

C語言中怎樣表示x的范圍在大于0小于10之間??

6、&& 與 || 的短路現象(P37頁)a++ && b++(當a=0時,不執行b++)a++ || b++(當a=1時,不執行b++)

7、含else 的if 語句

else、if 后只能有一條語句,若要跟多條語句,要用 { } 括起來

8、scanf(“%dn” , &x);

錯誤

!注意!

scanf(“%d” , &x);

正確

9、if 子句中嵌套帶有else 的if語句

if 子句中嵌套不帶else 的if語句

else與相鄰最近的沒有else的if相結合(舉例!)

10、在else 子句中嵌套if語句

例4.5中注意

scanf(“%d” , &g);注意 & 號 注意英文 , 而不是,11、條件表達式構成的選擇結構(C語言中唯一的三目運算符)格式如下:

表達式1 ? 表達式2 : 表達式3 當“表達式1”的值為非零時選擇“表達式2”為零時選擇“表達式3” 舉例 y = x >10 ? 100 : 200

怎么解釋??

舉例printf(“abs(x)= %dn” , x < 0 ?(-1)* x : x);見程序------“求絕對值”

12、switch 語句說明(P43頁)

13、goto語句了解即可,初學者盡量不要用goto語句,濫用goto語句將使程序混亂,見程序------“goto語句”

下載上嵌淺談C語言學習心得word格式文檔
下載上嵌淺談C語言學習心得.doc
將本文檔下載到自己電腦,方便修改和收藏,請勿使用迅雷等下載。
點此處下載文檔

文檔為doc格式


聲明:本文內容由互聯網用戶自發貢獻自行上傳,本網站不擁有所有權,未作人工編輯處理,也不承擔相關法律責任。如果您發現有涉嫌版權的內容,歡迎發送郵件至:645879355@qq.com 進行舉報,并提供相關證據,工作人員會在5個工作日內聯系你,一經查實,本站將立刻刪除涉嫌侵權內容。

相關范文推薦

    單片機C語言學習心得

    8、指針的使用 8.1 在定義的時候,*ap中的‘*’是指針類型說明符;在進行指針預算時,x = *ap 中的‘*’是指針運算符。 8.2 如果在已定義好的指針變量,并引用,即 int *ap, int a; a......

    C語言學習心得體會

    篇一:c語言心得體會作業 c語言心得體會 學習c語言已經一個學期了,剛開始學習的時候老是感覺力不從心。雖然認真聽課了,但是并不能理解它。這種情況到了后來才有所改變。 之所......

    c語言學習心得體會

    c語言學習心得體會 c語言作為一種計算機的語言,我們學習它,有助于我們更好的了解計算機,與計算機進行交流。其語言功能豐富、表達能力強、使用靈活方便、既具有高級語言的優點,......

    C語言學習心得報告

    C語言學習心得報告 看了一段時間的《C和指針》,這樣看的效果不是很好,看著書本當時是懂了,有點恍然大悟的感覺,但是發現并不能真正的把理解的內容加入到自己程序當中,不能很好的......

    c語言學習心得體會

    c語言程序設計學習心得體會 下面是對C語言中有許多重要知識的總結:1、一些基本的函數和基本數據類型的應用。其中,基本數據類型分為整型、浮點型、字符型、枚舉類型。基本函數......

    c語言學習心得體會

    c語言學習心得體會 c語言學習心得體會一:c語言學習心得體會 c語言作為一種計算機的語言,我們學習它,有助于我們更好的了解計算機,與計算機進行交流,因此,c語言的學習對我們尤其......

    c語言學習心得體會

    c語言學習心得體會 想學好C語言,交流是必須的,尤其是學習C語言的新手,以下是小編搜集并整理的c語言有關內容。 c語言學習心得體會學習C語言已經一年多,對C也算得上半個入門者,期......

    單片機C語言學習心得

    8、指針的使用 8.1 在定義的時候,*ap中的‘*’是指針類型說明符; 在進行指針預算時,x = *ap 中的‘*’是指針運算符。 8.2 如果在已定義好的指針變量,并引用,即 int *ap, int a;......

主站蜘蛛池模板: 亚洲中文字幕av每天更新| 熟妇的味道hd中文字幕| 麻豆精品秘?一区二区三区| 鸭子tv国产在线永久播放| 美女又黄又免费的视频| 亚洲欧洲国产成人综合在线观看| 国产香蕉尹人在线视频你懂的| 日本丰满熟妇videossex| 日韩精品无码免费专区午夜不卡| 亚洲中文字幕在线第六区| 欧日韩无套内射变态| 国产精品无码免费播放| 国产成人亚洲综合网站小说| 老司机午夜永久免费影院| 96精品久久久久久久久久| 99欧美日本一区二区留学生| 国产伦孑沙发午休精品| 国产日产欧产美韩系列麻豆| 亚洲精品无码高潮喷水a片软| 99久久九九社区精品| 自拍亚洲一区欧美另类| 色婷婷国产精品秘?免| 无码人妻精品一区二区三18禁| 久久丫精品系列| 少妇被粗大的猛烈进出视频| 亚洲色大成网站www在线观看| 国产手机精品一区二区| 国产男女猛烈视频在线观看| 最新国产精品无码| 亚洲变态另类天堂av手机版| 精品亚洲麻豆1区2区3区| 2021无码最新国产在线观看| aaaaa级少妇高潮大片免费看| 欧美乱码伦视频免费| 无人区乱码一区二区三区| 久久精品www人人爽人人| 久久久综合亚洲色一区二区三区| 国产 浪潮av性色四虎| 久久成人国产精品无码| 精品无码国产自产在线观看水浒传| 女人扒开下面无遮挡|