久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

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

QQ登錄

只需一步,快速開(kāi)始

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

ARM嵌入式學(xué)習(xí)之-----潛龍勿用

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:105323 發(fā)表于 2016-2-24 18:00 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
天下難事必作于易,天下大事必作于細(xì)----------有感于網(wǎng)絡(luò)連載學(xué)習(xí)教程《嵌入式Linux學(xué)習(xí)手冊(cè)》開(kāi)篇之語(yǔ),故也將之作為步入嵌入式學(xué)習(xí)的開(kāi)篇詞以自勉-  
我29了,當(dāng)立而未立,現(xiàn)在開(kāi)始確實(shí)太晚了,可我別無(wú)選擇,性格決定命運(yùn),命運(yùn)將我推到了這個(gè)時(shí)代的帝都,我別無(wú)選擇,還好這是我的興趣所在,so...
​#include“hope.h”   
​​#include“ persistence.h”
#include“ wisdom.h”

initialise......
START UP
main( )   
-------------------------------------------------------------------//2015/5/20晚追加  
1.ARM 系列CPU與對(duì)應(yīng)嵌入式操作系統(tǒng)的關(guān)系

要準(zhǔn)備涉足基于ARM的嵌入式操作系統(tǒng)了,面對(duì)各系列內(nèi)核的ARM處理器與嵌入式操作系統(tǒng),一直搞不清為什么嵌入式linux無(wú)法在諸如51和ARMcortex M4系列CPU上運(yùn)行,經(jīng)過(guò)一夜的查詢終于搞清楚了,關(guān)鍵在于CPU是否具有MMU,ARM cortexM4是一個(gè)主打控制功能兼具一定DSP功能的16/32位MCU,不具備MMU,所以只能運(yùn)行如uc/osII這樣的操作系統(tǒng),而ARMcortex A系列CPU則具備MMU功能,也同時(shí)具備更快的運(yùn)行速度,所以可以運(yùn)行完備的嵌入式linux操作系統(tǒng)。​
夜深了,明早繼續(xù)消化,編輯........​
2015/5/20----------------------------------------------------------------------------------
2.MCU --​STM32F407具備OTP(OneTime Programable)存儲(chǔ)器
MCU按其存儲(chǔ)器類型可分為MASK(掩模)ROM、OTP(一次性可編程)ROM、FLASH ROM等類型。MASKROM的MCU價(jià)格便宜,但程序在出廠時(shí)已經(jīng)固化,適合程序固定不變的應(yīng)用場(chǎng)合;FLASHROM的MCU程序可以反復(fù)擦寫(xiě),靈活性很強(qiáng),但價(jià)格較高,適合對(duì)價(jià)格不敏感的應(yīng)用場(chǎng)合或做開(kāi)發(fā)用途;OTPROM的MCU價(jià)格介于前兩者之間,同時(shí)又擁有一次性可編程能力,適合既要求一定靈活性,又要求低成本的應(yīng)用場(chǎng)合,尤其是功能不斷翻新、需要迅速量產(chǎn)的電子產(chǎn)品。​
2015/5/24
3.C語(yǔ)言#ifdef的用法
​C語(yǔ)言知識(shí)不精啊 剛開(kāi)始代碼分析就遇到坎坎了,一點(diǎn)點(diǎn)回憶,一點(diǎn)點(diǎn)積累吧~~
​#ifdef是C語(yǔ)言中預(yù)處理功能(宏定義,文件包含,條件編譯)中的條件編譯功能,具體格式如下:
#ifdef   x             #ifdef   x     
................               #definex
.................​               ................
#endif​  x            #endif   x
作用是先測(cè)試X是否被宏定義過(guò),如果沒(méi)有的話則條件指示值為真,此時(shí)執(zhí)行​#ifdef  x與#endif之間的語(yǔ)句,因?yàn)闆](méi)有被定義過(guò),所以中間的執(zhí)行語(yǔ)句一般加入#define x進(jìn)行宏定義;反之則跳過(guò),執(zhí)行#endif x后的語(yǔ)句。
條件指示符最重要的作用在于防止頭文件的重復(fù)包含和編譯​​
​千萬(wàn)不要忽略了頭件的中的#ifndef,這是一個(gè)很關(guān)鍵的東西。比如你有兩個(gè)C文件,這兩個(gè)C文件都include了同一個(gè)頭文件。而編譯時(shí),這兩個(gè)C文件要一同編譯成一個(gè)可運(yùn)行文件,于是問(wèn)題來(lái)了,大量的聲明沖突。   還是把頭文件的內(nèi)容都放在#ifndef和#endif中吧。不管你的頭文件會(huì)不會(huì)被多個(gè)文件引用,你都要加上這個(gè)。一般格式是這樣的:   #ifndef<標(biāo)識(shí)>   #define <標(biāo)識(shí)>   ......   #endif    <標(biāo)識(shí)>在理論上來(lái)說(shuō)可以是自由命名的,但每個(gè)頭文件的這個(gè)“標(biāo)識(shí)”都應(yīng)該是唯一的。標(biāo)識(shí)的命名規(guī)則一般是頭文件名全大寫(xiě),前后加下劃線,并把文件名中的“.”也變成下劃線,如:
stdio.h    #ifndef_STDIO_H_
......  
#endif
#ifndef xxx//如果沒(méi)有定義xxx
#define xxx//定義xxx
#endif //結(jié)束如果  
這個(gè)用法主要是在頭文件中,主要是為了防止類重復(fù)的include,所以在類的頭文件之前加上前面兩個(gè),用類名替代xxx,在最后加上最后一句。

更全的解釋在百度文庫(kù)中《C語(yǔ)言之詳解#ifdef等宏及妙用》放在kindle零碎時(shí)間看​
2015/5/25----------------------------------------------------------------------------------​
今天晚上沒(méi)有加班,把delay.c中的各種延時(shí)函數(shù)給看完了,同時(shí)也對(duì)UCOS有了一定理解,讓我慚愧的是連C語(yǔ)言中的!,~意思都記不大清楚了模模糊糊能猜對(duì)意思,就是不大確定,這記性。。。
2015/5/28----------------------------------------------------------------------------------​
在CM3/CM4中,SRAM最低1M地址范圍與片內(nèi)外設(shè)的最低1M地址范圍具備位帶(bitband)功能,也就是說(shuō)最低1M地址范圍的每個(gè)bit位地址都可以用一個(gè)32位字的別名來(lái)表示,引入位帶操作,其中一個(gè)好處就是可以對(duì)單個(gè)IO口進(jìn)行操作,最簡(jiǎn)單就是通過(guò)將0或1賦值給單個(gè)IO口,控制其輸出狀態(tài),具體推導(dǎo)公式見(jiàn)手冊(cè);
匯編編程:在ARM的RISC指令集中,數(shù)據(jù)從內(nèi)存與寄存器中移動(dòng),只能通過(guò)LDR/STR​進(jìn)行   不能用MOV指令,MOV指令只能用于寄存器之間數(shù)據(jù)的轉(zhuǎn)移,或者立即數(shù)與寄存器之間的轉(zhuǎn)移;
在X86的CISC指令集中,是可以用MOV指令在內(nèi)存與寄存器之間進(jìn)行數(shù)據(jù)轉(zhuǎn)移操作的。
這是RISC與CISC之間比較大的不同之處。​
ARM匯編指令:ORR.W 是對(duì)32位數(shù)進(jìn)行或操作;不加是對(duì)16位數(shù)進(jìn)行或操作。​
2015/5/31----------------------------------------------------------------------------------
不求甚解是我最大的毛病,今天看程序,有一個(gè)地方不明白,本想放過(guò)去以后再說(shuō),但好奇心還是促使我查了​一下,這一查才知道,這個(gè)點(diǎn)竟是如此重要,用某博客釋疑文章來(lái)說(shuō)“我認(rèn)為這是區(qū)分C程序員和嵌入式系統(tǒng)程序員的最基本的問(wèn)。搞嵌入式的家伙們經(jīng)常同硬件、中斷、RTOS等等打交道,所有這些都要求用到volatile變量.......”看完整篇文章后確實(shí)受益匪淺,也暗自慶幸自己沒(méi)有草草放過(guò)。故下面將原文轉(zhuǎn)發(fā):
__I、 __O、__IO是什么意思? 這是ST庫(kù)里面的宏定義,定義如下:
​#define__I volatile const  
​#define__O volatile  
​#define__IO volatile
顯然,這三個(gè)宏定義都是用來(lái)替換成volatile 和 const 的,所以我們先要了解這兩個(gè)關(guān)鍵字的作用: volatile 簡(jiǎn)單的說(shuō),就是不讓編譯器進(jìn)行優(yōu)化,即每次讀取或者修改值的時(shí)候,都必須重新從內(nèi)存或者寄存器中讀取或者修改。 一般說(shuō)來(lái),volatile用在如下的幾個(gè)地方: 1、中斷服務(wù)程序中修改的供其它程序檢測(cè)的變量需要加volatile; 2、多任務(wù)環(huán)境下各任務(wù)間共享的標(biāo)志應(yīng)該加volatile; 3、存儲(chǔ)器映射的硬件寄存器通常也要加volatile說(shuō)明,因?yàn)槊看螌?duì)它的讀寫(xiě)都可能由不同意義; 我認(rèn)為這是區(qū)分C程序員和嵌入式系統(tǒng)程序員的最基本的問(wèn)題。搞嵌入式的家伙們經(jīng)常同硬件、中斷、RTOS等等打交道,所有這些都要求用到volatile變量。不懂得volatile的內(nèi)容將會(huì)帶來(lái)災(zāi)難。假設(shè)被面試者正確地回答了這是問(wèn)題(嗯,懷疑是否會(huì)是這樣),我將稍微深究一下,看一下這家伙是不是直正懂得volatile完全的重要性。
1)一個(gè)參數(shù)既可以是const還可以是volatile嗎?解釋為什么。
2);一個(gè)指針可以是volatile 嗎?解釋為什么。
​3);下面的函數(shù)有什么錯(cuò)誤: intsquare(volatile int*ptr) { return*ptr **ptr; }
1)是的。一個(gè)例子是只讀的狀態(tài)寄存器。它是volatile因?yàn)樗赡鼙灰庀氩坏降馗淖儭K莄onst因?yàn)槌绦虿粦?yīng)該試圖去修改它。
​2);是的。盡管這并不很常見(jiàn)。一個(gè)例子是當(dāng)一個(gè)中服務(wù)子程序修該一個(gè)指向一個(gè)buffer的指針時(shí)。
3)這段代碼有點(diǎn)變態(tài)。這段代碼的目的是用來(lái)返指針*ptr指向值的平方,但是,由于*ptr指向一個(gè)volatile型參數(shù),編譯器將產(chǎn)生類似下面的代碼:
intsquare(volatile int *ptr)
{ inta,b;
​a= *ptr;
b= *ptr;
returna *b; }
由于*ptr的值可能被意想不到地該變,因此a和b可能是不同的。結(jié)果,這段代碼可能返不是你所期望的平方值!
正確的代碼如下:
longsquare(volatile int *ptr)
{ inta;
a= *ptr;
​returna * a; }
const
​只讀變量,即變量保存在只讀靜態(tài)存儲(chǔ)區(qū)。編譯時(shí),如何嘗試修改只讀變量,則編譯器提示出錯(cuò),就能防止誤修改。
const與define 兩者都可以用來(lái)定義常量,但是const定義時(shí),定義了常量的類型,所以更精確一些(其實(shí)const定義的是只讀變量,而不是常量)。#define只是簡(jiǎn)單的文本替換,除了可以定義常量外,還可以用來(lái)定義一些簡(jiǎn)單的函數(shù),有點(diǎn)類似內(nèi)置函數(shù)。const和define定義的常量可以放在頭文件里面。(小注:可以多次聲明,但只能定義一次) const與指針
intme;
constint * p1=&me; //p1可變,*p1不可變 const 修飾的是*p1,即*p1不可變
int* const p2=&me; //p2不可變,*p2可變 const 修飾的是p2,即p2不可變
constint *const p3=&me; //p3不可變,*p3也不可變 前一個(gè)const 修飾的是*p3,后一個(gè)const 修飾的是p3,兩者都不可變
前面介紹了volatile 和 const的用法,不知道大家了解了沒(méi)?了解了后,下面的講解就更加容易了:
__I:輸入口。既然是輸入,那么寄存器的值就隨時(shí)會(huì)外部修改,那就不能進(jìn)行優(yōu)化,每次都要重新從寄存器中讀取。也不能寫(xiě),即只讀,不然就不是輸入而是輸出了。
__O:輸出口,也不能進(jìn)行優(yōu)化,不然你連續(xù)兩次輸出相同值,編譯器認(rèn)為沒(méi)改變,就忽略了后面那一次輸出,假如外部在兩次輸出中間修改了值,那就影響輸出
__IO:輸入輸出口,同上
為什么加下劃線? 原因是:避免命名沖突 一般宏定義都是大寫(xiě),但因?yàn)檫@里的字母比較少,所以再添加下劃線來(lái)區(qū)分。這樣一般都可以避免命名沖突問(wèn)題,因?yàn)楹苌偃诉@樣命名,這樣命名的人肯定知道這些是有什么用的。 經(jīng)常寫(xiě)大工程時(shí),都會(huì)發(fā)現(xiàn)老是命名沖突,要不是全局變量沖突,要不就是宏定義沖突,所以我們要盡量避免這些問(wèn)題,不然出問(wèn)題了都不知道問(wèn)題在哪里。​
2015/6/1----------------------------------------------------------------------------------
​遇到很多IO口設(shè)置程序都有GPIO_TypeDef*GPIOx  就如同下面這句一樣
​voidGPIO_AF_Set(GPIO_TypeDef* GPIOx,u8 BITx,u8 AFx)費(fèi)了好一番腦筋才看明白
其實(shí)意思是定義了一個(gè)結(jié)構(gòu)體指針類型的變量GPIOx,類比于后面的​u8BITx,u8 AFx
請(qǐng)看下面一段程序
  __IO uint32_t OTYPER;
  __IO uint32_t OSPEEDR;
  __IO uint32_t PUPDR;   
  __IO uint32_t IDR;     
  __IO uint32_t ODR;     
  __IO uint16_t BSRRL;   
  __IO uint16_t BSRRH;   
  __IO uint32_t LCKR;   
  __IO uint32_t AFR[2];
} GPIO_TypeDef;
#define GPIOA             ((GPIO_TypeDef *) GPIOA_BASE)   //
void GPIO_AF_Set(GPIO_TypeDef* GPIOx,u8 BITx,u8AFx)
{  
GPIOx->AFR[BITx>>3]&=~(0X0F<<((BITx&0X07)*4));
GPIOx->AFR[BITx>>3]|=(u32)AFx<<((BITx&0X07)*4);
}   
​該段程序的作用是對(duì)GPIOA的寄存器進(jìn)行設(shè)置,
首先通過(guò) ((GPIO_TypeDef*)GPIOA_BASE)對(duì)GPIOA_BASE(A系IO口的基址)指向結(jié)構(gòu)體GPIO_TypeDef的起始地址,并且用宏替換成GPIOA
  #defineGPIOA             ((GPIO_TypeDef *) GPIOA_BASE)
GPIOA是一個(gè)GPIO_TypeDef型的 結(jié)構(gòu)體指針變量具備GPIO_TypeDef所有的成員變量類型這樣通過(guò)GPIOA基址加上不同成員的地址偏移量訪問(wèn)不同的寄存器,對(duì)GPIOA的各個(gè)IO口進(jìn)行設(shè)置,如果不#defineGPIOA             ((GPIO_TypeDef *) GPIOA_BASE)
那么GPIOx->AFR無(wú)法采用此方式訪問(wèn)成員變量,所以關(guān)鍵在于強(qiáng)制轉(zhuǎn)換成結(jié)構(gòu)體指針變量。
-----------------------
​今晚照著葫蘆畫(huà)瓢把LED等點(diǎn)亮了,關(guān)鍵在于又解決了一系列的小問(wèn)題主要列舉下面兩個(gè):頭文件包含#include一定別忘了了把包含文件的路徑給加進(jìn)去  否則會(huì)提示找不到文件無(wú)法打開(kāi)無(wú)該文件路徑等等;每個(gè)程序文件的末尾加一個(gè)空行,作為編譯器識(shí)別文件結(jié)束的標(biāo)志雖然只作為警告,但為追求完美,作為一個(gè)編程習(xí)慣還是回車(chē)一下,加上一空行為宜。
夜深了,又該睡了,下次安排在晚上10點(diǎn)半結(jié)束學(xué)習(xí),留半小時(shí)總結(jié)一天之得失​
2015/6/2--------------------------------------------------------------------------------------
​今晚蜂鳴器實(shí)驗(yàn):第一,我的較真精神應(yīng)該表?yè)P(yáng),不單單滿足于完成蜂鳴實(shí)驗(yàn),對(duì)于輸出是上拉還是下拉也進(jìn)行辨析,結(jié)果不論是上拉還是下拉,蜂鳴器都響,其實(shí)由原理圖得知,蜂鳴器響主要與拉電流有關(guān),IO口向外送電流催動(dòng)三極管導(dǎo)通,蜂鳴器鳴響。
那么再鞏固一下拉電流跟灌電流的概念​​,為加深理解,給出其相對(duì)應(yīng)的英文翻譯,就一目了然了
拉電流(sourcingcurrent),對(duì)一個(gè)端口而言,如果電流方向是向其外部流動(dòng)的則是“拉電流”​
灌電流(sink current),對(duì)一個(gè)端口而言,如果電流方向是向其內(nèi)部流動(dòng)的則是“灌電流”​
22:30  結(jié)束反思總結(jié)完睡覺(jué)。
記得每個(gè)周末都重新回顧一遍。​
2015/6/3------------------------------------------------------------------------------​
按鍵輸入實(shí)驗(yàn),沒(méi)看明白,​​不過(guò)關(guān)于IO口上拉下拉的設(shè)置有一些形象的認(rèn)識(shí),此實(shí)驗(yàn),IO口作為輸入,按鍵按下,IO口接地,IO口向地輸出電流,則IO設(shè)置為輸入上拉(sourcingcurrent)模式;反之按鍵接3.3V電平,按下按鍵后,IO口接入3.3V,這樣從3.3V向IO口灌入電流,這樣則IO設(shè)置為入下拉;如果設(shè)置IO口輸出模式,上下拉取決于是拉電流還是灌電流。
​2015/6/7--------------------------------------------------------------------------------
串口通信實(shí)驗(yàn)中,在輸入代碼的時(shí)候,由于括號(hào)用了漢字狀態(tài)下的括號(hào),編譯器提示出錯(cuò):expected a “)”或者source file is not valid UTF-8   經(jīng)過(guò)一段段的程序粘貼差錯(cuò)定位到出錯(cuò)語(yǔ)句的 ;
一溜煙兒,竟然連續(xù)三天沒(méi)有研究了,真可怕​,時(shí)間快的真可怕
2015/6/8--------------------------------------------------------------------------------​
​今天要轉(zhuǎn)變學(xué)習(xí)方式了,發(fā)現(xiàn)回顧前面看的章節(jié)時(shí)候,依然沒(méi)什么深刻的印象,可能雖說(shuō)是按一個(gè)個(gè)小工程來(lái)進(jìn)行練習(xí)的,也跟看書(shū)一樣,稍微零碎一點(diǎn),依然不系統(tǒng),松散,故先粗看一遍,然后直接上馬我的工程,由頂至下的設(shè)計(jì),各個(gè)模塊擊破,最后再進(jìn)行連接,這樣效率更高,針對(duì)性更強(qiáng),印象更深刻。
就這樣,摸著石頭過(guò)河吧
時(shí)間真的有些捉襟見(jiàn)肘,必須不斷想辦法去提高效率。​​
2015/6/10​-----------------------------------------------------------------------------------
最難啃的一塊骨頭,TFTLCD液晶顯示,我應(yīng)該抽出一段大的連續(xù)時(shí)間塊,把它啃下來(lái),有史以來(lái)比較復(fù)雜的設(shè)備驅(qū)動(dòng)程序​
2015/6/25
好吧,一眨眼已經(jīng)15天過(guò)去了,一對(duì)比才發(fā)現(xiàn)時(shí)間是如此經(jīng)不起蹉跎,真的過(guò)得太快了,期間有幾天看了,但沒(méi)勤于記錄,今日想起,已經(jīng)兩個(gè)周過(guò)去了~~~真是 快得令人唏噓啊
還是液晶屏的驅(qū)動(dòng)問(wèn)題,在線調(diào)試無(wú)法持續(xù)運(yùn)行,總是陷在一個(gè)延時(shí)程序中出不來(lái),我也試圖查找其原因,未果,于是在正點(diǎn)原子論壇上發(fā)了我第一個(gè)處女帖,希望早日獲得解答,以解惑,以及解決問(wèn)題的方法
2015/07/01
程序中的extern關(guān)鍵字
extern置于變量或者函數(shù)前,以表示變量或者函數(shù)的定義在別的文件中,提示編譯器遇到此變量或函數(shù)時(shí),在其它模塊中尋找其定義。另外,extern也可用來(lái)進(jìn)行鏈接指定。
​同一個(gè)變量或函數(shù)在程序中只能定義一次,如果程序文件A跟B都定義了該變量​或函數(shù),那么在編譯的時(shí)候是沒(méi)問(wèn)題的,因?yàn)榫幾g時(shí)是按文件編譯的,各個(gè)文件中定義的全局變量是互不透明的;當(dāng)進(jìn)行到鏈接階段時(shí),要把所有文件融合到一起,就會(huì)出現(xiàn)定義兩次的情況,就會(huì)報(bào)錯(cuò);
​extern的原理很簡(jiǎn)單,就是告訴編譯器:“你現(xiàn)在編譯的文件中,有一個(gè)標(biāo)識(shí)符雖然沒(méi)有在本文件中定義,但是它是在別的文件中定義的全局變量,你要放行!”
所以extern是一個(gè)該變量或函數(shù)在別處定義的一個(gè)聲明,可以多次出現(xiàn);而定義卻只能出現(xiàn)一次​因此在某個(gè)文件中引用一個(gè)全局變量的時(shí)候,需要用extern聲明一下

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

使用道具 舉報(bào)

本版積分規(guī)則

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

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

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 亚洲视频观看 | 日本手机在线 | 97综合在线| 欧美在线视频一区二区 | 亚洲在线视频 | 成人久草| 久久国产欧美日韩精品 | 正在播放国产精品 | 免费观看av| 超碰在线国产 | 日本不卡一区二区三区 | 人人做人人澡人人爽欧美 | 狠狠干夜夜草 | 精品九九 | 人人人人干 | .国产精品成人自产拍在线观看6 | 国产一区二区影院 | 国产美女福利在线观看 | 国产精品免费一区二区三区四区 | 国产一区二区在线视频 | 久久免费国产 | 伊人伊成久久人综合网站 | 久久性av | 99久久婷婷国产综合精品电影 | 久久亚洲一区二区三区四区 | 日韩色图视频 | 嫩草研究影院 | 国产91丝袜在线播放 | 国产一区二区三区久久久久久久久 | 国产日韩在线观看一区 | 成人免费视频网址 | 日韩免费 | 一区二区三区高清 | 高清av电影 | 中文字幕免费在线观看 | 98成人网| 久久精品网| 日本a∨精品中文字幕在线 亚洲91视频 | 午夜伦理影院 | 51ⅴ精品国产91久久久久久 | 久久精品网 |