一、如何控制單片機(jī)?
單片機(jī)的內(nèi)存映射圖解析
這里以STM32F429芯片為例,講解下單片機(jī)芯片內(nèi)存映射圖。從此圖中可以看到芯片的外設(shè)被分配了512M的空間,然而真正的外設(shè)其實(shí)沒有使用到512M的內(nèi)存空間。
然后我們操作外設(shè)時(shí),只需要操作它對應(yīng)的內(nèi)存地址即可。更加詳細(xì)的外設(shè)內(nèi)存地址,可以參考芯片的用戶手冊(不是數(shù)據(jù)手冊)的Memory map章節(jié)。
因?yàn)閱纹瑱C(jī)是將外設(shè)映射到內(nèi)存地址上,所以我們可以像操作內(nèi)存一樣來操作外設(shè)(寫/讀)。
我們在操作內(nèi)存時(shí)是通過地址來進(jìn)行操作的,由于單片機(jī)已經(jīng)將外設(shè)與內(nèi)存進(jìn)行了映射,所以我們在操作單片機(jī)外設(shè)時(shí)只需要操作外設(shè)映射的內(nèi)存地址就行。
內(nèi)存如何操作?
在C語言中操作內(nèi)存,我們可以用指針來進(jìn)行操作。在匯編語言中由于沒有指針這個概念,所以我們在操作地址時(shí)只能用一些內(nèi)存讀寫指令來完成。比如:LDR,STR
結(jié)構(gòu)體操作與宏定義操作的對比
C語言——宏定義形式
#define GPIOA (*(volatile uint32_t *)(0x000800E0))
#define GPIOA_DR (*(volatile uint32_t *)(0x000800E4))
#define GPIOA_MR (*(volatile uint32_t *)(0x00080108))
#define GPIOA_TR (*(volatile uint32_t *)(0x00080108))
C語言——結(jié)構(gòu)體操作
struct GPIOA_Reg{
volatile uint32_t dr;
volatile uint32_t mr;
volatile uint32_t tr;
}GPIOA_REG
匯編語言操作內(nèi)存
LDR r0, =0x00800010
MOV r1, #2
STR r1, [r0]
二、寄存器方式操作單片機(jī)
代碼結(jié)構(gòu)框架:
文件結(jié)構(gòu)
一個芯片頭文件:外設(shè)的地址宏定義以及外設(shè)相關(guān)的結(jié)構(gòu)體定義
查看芯片的用戶手冊(注意:不是數(shù)據(jù)手冊)中寄存器對應(yīng)的相應(yīng)地址。然后使用宏定義來將它們定義好,同時(shí)定義好結(jié)構(gòu)體來更加方便的管理外設(shè)寄存器組。這里以STM32F1系列為例
- ? 一個啟動文件:匯編編寫的、中斷向量表等
- ? 用戶代碼文件:剩余就是用戶代碼文件了
- ? 各個芯片的外設(shè)驅(qū)動函數(shù)編寫(讀/寫、控制)、以及用戶邏輯部分代碼。
三、使用HAL庫方式操作單片機(jī)
HAL庫與固件庫的區(qū)別
HAL全稱Hardware abstract layer(硬件抽象層),這是一個大家公認(rèn)并且遵守的一種函數(shù)名稱命名、資源定義。因?yàn)槭墙y(tǒng)一的命名規(guī)范,所以當(dāng)用戶更換芯片平臺后由于函數(shù)命名與所使用的資源都與具體硬件沒有關(guān)系,這樣就不需要修改用戶層代碼了。
而所謂的標(biāo)準(zhǔn)庫其實(shí)就是芯片廠商公司內(nèi)部自己命名與實(shí)現(xiàn)的庫并且各個廠商的命名規(guī)則不一樣,這樣就會導(dǎo)致可移植性變差。當(dāng)用戶更換了芯片平臺后由于它們各自的API函數(shù)不一樣就會導(dǎo)致用戶需要修改應(yīng)用層代碼。
HAL庫設(shè)計(jì)
1. HAL框架設(shè)計(jì)
2. HAL資源命名規(guī)則
HAL函數(shù)命名規(guī)則:
中斷與時(shí)鐘設(shè)置宏:
回調(diào)函數(shù)命名規(guī)則:
3. 文件結(jié)構(gòu):
一個芯片頭文件:外設(shè)的地址宏定義以及外設(shè)相關(guān)的結(jié)構(gòu)體定義
查看芯片的用戶手冊(注意:不是數(shù)據(jù)手冊)中寄存器對應(yīng)的相應(yīng)地址。然后使用宏定義來將它們定義好,同時(shí)定義好結(jié)構(gòu)體來更加方便的管理外設(shè)寄存器組。這里以STM32F1系列為例
一個啟動文件:匯編編寫的、中斷向量表等。
一個HAL庫全局頭文件:一些全局的宏定義以及包含其他外設(shè)頭文件
HAL庫文件:芯片外設(shè)的驅(qū)動函數(shù)
四、HAL庫組成說明
1. HAL庫的數(shù)據(jù)結(jié)構(gòu)體
- ? 外設(shè)句柄結(jié)構(gòu)體
- ? 初始化和配置結(jié)構(gòu)體
- ? 特定的處理結(jié)構(gòu)體(讀寫/控制)
** 外設(shè)句柄結(jié)構(gòu)體(跟硬件不相關(guān)):**
比如:下面這個串口結(jié)構(gòu)體
typedef struct
{
USART_TypeDef *Instance; /* USART registers base address */
USART_InitTypeDef Init; /* Usart communication parameters */
uint8_t *pTxBuffPtr;/* Pointer to Usart Tx transfer Buffer */
uint16_t TxXferSize; /* Usart Tx Transfer size */
__IO uint16_t TxXferCount;/* Usart Tx Transfer Counter */
uint8_t *pRxBuffPtr;/* Pointer to Usart Rx transfer Buffer */
uint16_t RxXferSize; /* Usart Rx Transfer size */
__IO uint16_t RxXferCount; /* Usart Rx Transfer Counter */
DMA_HandleTypeDef *hdmatx; /* Usart Tx DMA Handle parameters */
DMA_HandleTypeDef *hdmarx; /* Usart Rx DMA Handle parameters */
HAL_LockTypeDef Lock; /* Locking object */
__IO HAL_USART_StateTypeDef State; /* Usart communication state */
__IO HAL_USART_ErrorTypeDef ErrorCode;/* USART Error code */
}USART_HandleTypeDef;
初始化結(jié)構(gòu)體(跟硬件相關(guān)):
比如:下面這個串口硬件相關(guān)的結(jié)構(gòu)體
typedef struct
{
uint32_t BaudRate; /*!< This member configures the UART communication baudrate.*/
uint32_t WordLength; /*!< Specifies the number of data bits transmitted or received
in a frame.*/
uint32_t StopBits; /*!< Specifies the number of stop bits transmitted.*/
uint32_t Parity; /*!< Specifies the parity mode. */
uint32_t Mode; /*!< Specifies wether the Receive or Transmit mode is enabled or
disabled.*/
uint32_t HwFlowCtl; /*!< Specifies wether the hardware flow control mode is enabled
or disabled.*/
uint32_t OverSampling; /*!< Specifies wether the Over sampling 8 is enabled or
disabled,
to achieve higher speed (up to fPCLK/8).*/
}UART_InitTypeDef;
特定的處理結(jié)構(gòu)體(跟硬件有關(guān)):
比如:下面這個ADC處理處理結(jié)構(gòu)體
typedef struct
{
uint32_t Channel; /*!< Specifies the channel to configure into ADC regular group.
This parameter can be a value of @ref ADC_channels */
uint32_t Rank; /*!< Specifies the rank in the regular group sequencer.
This parameter must be a number between Min_Data = 1 and Max_Data = 16 */
uint32_t SamplingTime; /*!< Sampling time value to be set for the selected channel.
Unit: ADC clock cycles
Conversion time is the addition of sampling time and processing time (12 ADC clock cycles at ADC resolution 12 bits, 11 cycles at 10 bits, 9 cycles at 8 bits, 7 cycles at 6 bits).
This parameter can be a value of @ref ADC_sampling_times
Caution: This parameter updates the parameter property of the channel, that can be used into regular and/or injected groups.
If this same channel has been previously configured in the other group (regular/injected), it will be updated to last setting.
Note: In case of usage of internal measurement channels (VrefInt/Vbat/TempSensor),
sampling time constraints must be respected (sampling time can be adjusted in function of ADC clock frequency and sampling time setting)
Refer to device datasheet for timings values, parameters TS_vrefint, TS_temp (values rough order: 4us min). */
uint32_t Offset; /*!< Reserved for future use, can be set to 0 */
}ADC_ChannelConfTypeDef;
2. HAL庫公共資源
HAL Status:狀態(tài)枚舉
Typedef enum
{
HAL_OK = 0x00,
HAL_ERROR = 0x01,
HAL_BUSY = 0x02,
HAL_TIMEOUT = 0x03
} HAL_StatusTypeDef;
HAL Locked:用于防止共享資源被意外訪問
typedef enum
{
HAL_UNLOCKED = 0x00, /*!< Resources unlocked */
HAL_LOCKED = 0x01 /*!< Resources locked */
} HAL_LockTypeDef;
公共的宏定義:NULL 和 HAL_MAX_DELAY
#ifndef NULL
#define NULL (void *) 0
#endif
#define HAL_MAX_DELAY 0xFFFFFFFF
3. HAL庫中斷回調(diào)函數(shù)實(shí)現(xiàn)說明
(1)使用 __ weak 定義好回調(diào)函數(shù)。如果用戶自己重寫了回調(diào)函數(shù),那么編譯器就會使用用戶重寫的這個回調(diào)函數(shù)。其中__ weak這個關(guān)鍵字是編譯器定義的。
(2)使用函數(shù)指針。定義一個全局的函數(shù)指針變量,在初始化函數(shù)時(shí)將我們自定義的回調(diào)函數(shù)賦值給這個全局的函數(shù)指針變量(這一步也叫做:注冊)。然后再中斷函數(shù)中通過這個全局的函數(shù)指針變量來調(diào)用我們自定義的回調(diào)函數(shù)。
-
單片機(jī)
+關(guān)注
關(guān)注
6030文章
44489瀏覽量
631960 -
STM32
+關(guān)注
關(guān)注
2264文章
10854瀏覽量
354288 -
內(nèi)存映射
+關(guān)注
關(guān)注
0文章
14瀏覽量
7410
發(fā)布評論請先 登錄
相關(guān)推薦
評論