欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1793|回復: 0
打印 上一主題 下一主題
收起左側

ARM嵌入式學習之-----潛龍勿用

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

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

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

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

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

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

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

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

快速回復 返回頂部 返回列表