一、什么是位帶操作
位帶操作簡單講就是將一個對二進制位的操作映射到一個32位的地址上,通過給這個地址置0或1來給這個二進制位置0或1。
二、CM3的位帶操作
在CM3支持的位段中,有兩個區中實現了位段。
其中一個是 SRAM 區的最低 1MB 范圍,0x20000000‐0x200FFFFF(SRAM 區中的最低 1MB);
第二個則是片內外設區的最低 1MB范圍,0x40000000‐0x400FFFFF(片上外設區中的最低 1MB)。
從上圖可以看出,SRAM中地址為0x20000000單元的32位Bit可以分別被映射到0x22000000-0x2200008F的128字節的地址范圍中,即0x20000000-0x20000003的4個字節的32位Bit被分別映射到地址為0x22000000, 0x22000004, 0x22000008, 0x2200000C, 0x22000010, …, 0x22000080, 0x22000084,0x22000088, 0x2200008C的32個地址上。
同樣,對片內外設寄存器的操作也是類似的,只不過地址的范圍不同。片內外設中地址為0x40000000單元的32位Bit可以分別被映射到0x42000000-0x2200008F的128字節的地址范圍中,即0x40000000-0x40000003的4個字節的32位Bit被分別映射到地址為0x42000000, 0x42000004, 0x42000008, 0x4200000C, 0x42000010, …, 0x42000080, 0x42000084,0x42000088, 0x4200008C的32個地址上。
三、編程中如何進行位帶地址轉換
對SRAM位帶區的某個比特,記它所在字節地址為A,位序號為n(0<=n<=7),則該比特在別名區的地址為:
AliasAddr=0x22000000+((A-0x20000000)*8+n)*4=0x22000000+(A-0x20000000)*32+n*4
對于片上外設位帶區的某個比特,記它所在字節的地址為A,位序號為n(0<=n<=7),則該比特在別名區的地址為:
AliasAddr=0x42000000+((A-0x40000000)*8+n)*4=0x42000000+(A-0x40000000)*32+n*4
對于SRAM中的某個地址肯定是在0x20000000~0x200FFFFF之間,而在片內外設的某個地址肯定在0x40000000~0x400FFFFF之間,假設地址為A,可以通過:
A &0xF0000000 + 0x02000000
得到地址為A的數據對應的位帶區的首地址,后面的(A-0x20000000)*32+n*4和(A-0x40000000)*32+n*4可以統一為(A-A&0xF0000000)*32+n*4,則兩個區間的位帶地址的表達式可以統一為:
AliasAddr= (A& 0xF0000000 + 0x02000000)+ (A-A&0xF0000000)*32+n*4
將乘法運算換成左移位運算,則表示為:
AliasAddr= (A& 0xF0000000 + 0x02000000)+ ((A-A&0xF0000000)<<5)+(n<<2)
而(A-A&0xF0000000)實際上就是地址A相對于0x20000000或者0x40000000的偏移地址,只需要保留低20位,高12位取0即可,所以(A-A&0xF0000000)等效于:A&0xFFFFF
在C編程中定義如下宏進行地址轉換:
#defineBITBAND(addr,n) ((addr&0xF0000000) + 0x02000000 +((addr&0xFFFFF)<<5) + (n<<2))
下面的宏將地址轉換成變量形式:
#defineMEM_ADDR(addr) *((volatile unsigned long *)(addr))
下面的宏將某一具體地址及第n位映射到位帶
#defineBIT_ADDR(addr,n) MEM_ADDR(BITBAND(addr,n))
有了這些宏定義,就可以對位映射到位帶區了。例如對GPIOA的數據輸出寄存器的第0為操作,GPIOA的基地址為0x40010800,而端口輸出寄存器GPIOx_ODR的地址偏移為12,則GPIOA_ODR寄存器的地址為0x4001080C,可以定義如下的宏:
#definePAOut(n) BIT_ADDR(0x4001080C , n)
這樣,如果在程序中想在GPIOA_0輸出低電平,只需要如下賦值語句:
PAOut(0) = 0;
四、應用實例
1、硬件連接:現在將STM32F103ZET6的GPIOC的0-7引腳連接到共陽數碼管的a-h端。
2、采用STM32F10X外設庫函數,這里使用到stm32f10x_rcc.h, stm32f10x_rcc.c, stm32f10x_gpio.h, stmf10x_gpio.c,項目的創建過程請參看:https://blog.csdn.net/fanxp66/article/details/80215090
3、新建led.h頭文件,輸入以下內容:
/*
LED頭文件,GPIO初始化
GPIO位帶操作
*/
#ifndef __LED__H
#define __LED__H
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
//定義位帶地址宏
#define BITBAND(addr,bitnum) ((addr&0xF0000000) + 0x02000000 + ((addr&0x000FFFFF)<<5) + (bitnum<<2))
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
#define BIT_ADDR(addr,bitnum) MEM_ADDR(BITBAND(addr,bitnum))
//IO口地址映射
//數據輸出寄存器地址
#define GPIOC_ODR_Addr (GPIOC_BASE + 12)
//定義GPIOC的位地址變量宏,位輸出宏
#define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n)
#define LED_PORT GPIOC
#define LED_PIN (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7)
#define LED_PORT_RCC RCC_APB2Periph_GPIOC
void LED_Init(void);
#endif
4、新建led.c程序文件,內容如下:
#include "led.h"
void LED_Init()
{
GPIO_InitTypeDef GPIOC_0_mode;
RCC_APB2PeriphClockCmd( LED_PORT_RCC, ENABLE ); //使能GPIOC時鐘
GPIOC_0_mode.GPIO_Pin = LED_PIN;
GPIOC_0_mode.GPIO_Speed = GPIO_Speed_50MHz;
GPIOC_0_mode.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIOC_0_mode);
}
5、將led.c加入到項目的"User"組中,在項目配置中,配置C/C++的包含路徑有能找到led.h的路徑。
6、修改main.c程序,內容為:
#include "stm32f10x.h"
#include "stm32f10x_rcc.h"
#include "led.h"
void delay(int t)
{
int i;
for( ;t>0; t--)
for(i=0;i<1000;i++);
}
int main()
{
u32 i,j;
//共陽數碼管’0’-‘9’的顯示碼
u32 LED[10] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
LED_Init();
while(1)
{
for(i=0;i<10;i++)
{
//根據 LED[n]數組的值決定數碼管各個段位的顯示
for(j=0; j<8; j++)
if( ~(LED[i]) & 0x1< PCout(j) = 0; else PCout(j) = 1; delay(10000); } } }
上一篇:在STM32項目中使用SysTick實現延時(STM32_06)
下一篇:使用STM32固件庫函數操作控制LED燈(STM32_04)
推薦閱讀
史海拾趣
靜芯微電子(ElecSuper)成立于XXXX年,由一群富有遠見和熱情的電子工程師共同創立。公司從一開始就專注于ESD(靜電放電)/TVS(瞬態電壓抑制器)系列器件的研發,致力于為客戶提供高質量的靜電保護和電壓穩定解決方案。通過不斷的技術創新和產品優化,靜芯微電子逐漸在ESD/TVS領域取得了突破,并積累了大量的客戶基礎。
作為電子行業的領軍企業,BEL始終注重技術創新和研發。公司不斷投入大量資源用于新產品的研發和創新,努力引領行業趨勢。近年來,BEL在無人機、太陽能電池組等領域取得了顯著成果,推出了一系列具有創新性和市場競爭力的產品,為公司的持續發展注入了新的活力。
DIOTECH公司成立于電子行業的黃金時期,憑借其創始人在半導體領域的深厚造詣,公司迅速在高性能處理器領域取得了技術突破。通過不斷優化產品設計和生產工藝,DIOTECH的產品在性能和穩定性上均達到了行業領先水平,逐漸贏得了市場的認可。隨著智能手機的普及,DIOTECH的高性能處理器成為了市場上的搶手貨,公司的營收和市場份額均實現了快速增長。
隨著技術的不斷進步,AFOP在光纖元件領域取得了重大突破。公司成功研發出一系列高品質的光纖元件和集成模塊,如波分復用光電二極管、光衰減器等,這些產品在光網通信領域具有廣泛的應用。同時,AFOP還注重產品升級和迭代,根據市場需求和客戶反饋,不斷優化產品性能和質量,贏得了客戶的廣泛認可。
[摘要]有400多萬人口的新加坡在"全球IT網絡化"方面是亞洲最好的、世界排名第二。政府的指導思想是"許多機構,一個政府",提供無縫、集成的公共服務。 新加坡是19世紀作為英國的一個貿易港口建立起來的。土地空間和勞動力市場的狹小,使得新加 ...… 查看全部問答∨ |
|
net2005 用C++開發PDA程序,不能加載COm組件? 我在NET 2005 用C++開發智能設備程序,也就是PDA上的程序,不能加載COM組件,就是Grid control,請問應該怎么辦? … 查看全部問答∨ |
|
stm32103xx請教DMA(DMA_Mode)使用問題! stm32手冊上這樣描述:循環模式:循環模式用于處理循環緩沖區和連續的數據傳輸(如ADC的掃描模式)。在DMA_CCRx寄存器中的CIRC位用于開啟這一功能。當啟動了循環模式,數據傳輸的數目變為0時,將會自動地被恢復成配置通道時設置的初值,DMA操作 ...… 查看全部問答∨ |
|