非操作系統下GPIO口控制器及LED燈編程
GPIO控制器
概述
S3C6410 共有 187 根 IO 口,分成 17 個 PORT,每根 IO 口可以被用在輸入引腳線、輸出引腳線和其它功能引腳線使用,可以通過每個端口自帶的控制寄存器進行功能配置。
‘
內部架構
- GPIO控制器掛在APB總線,屬於低速設備。
- 控制器包括寄存器文件和相應的功能電路組成,通過寄存器可以控制功能電路按照用戶的方式進行工作。
- 整個控制器包括 alive-part , off-part 兩個部分, 區別在於sleep mode 時是否有電源供應,在 alive-part 時有電源供給,所以其端口可用作 wake –up 喚醒信號
端口寄存器
GPIO控制寄存器
- 功能 – 配置相應端口的功能
GPIO數據寄存器
- 數據寄存器每個bit位對應相應端口的IO線
- 如果該IO線被用做輸入口引腳,該bit位隨着引腳線電平的變化而變化(其對應值爲0或者1);
- 如果該IO線被用作輸出口引腳,則該bit位值爲1時,外面對應引腳線爲高電平(一般爲3.3v左右),則該bit位值爲0時,外面對應引腳線爲低電平(一般爲略大於0V)
GPIO上拉寄存器
- 該寄存器可以對 arm 一些特殊io做上拉或下拉處理,這在一些場合是非常有用的,避免了在pcb上加上拉或下拉電阻,能夠簡化外部電路設計
非操作系統LED燈閃爍
開發步驟
- 看懂硬件圖
- 編寫驅動
- 編寫應用程序
- 使用工具
- 系統調試
開發板上二極管
讀電路圖
S3C6410芯片手冊
程序框架
- 彙編
;asses.s內容
AREA Init, CODE READONLY
ENTRY
_start
B Main
END
- 編寫應用程序
// ledapp.c
void main()
{
ledconfig();
for(…)
{
ledon();delay();
ledoff();delay();
}
}
- 編寫驅動
// leddrv.c
void ledconfig()
{
……
}
void ledon()
{
……
}
void ledoff()
{
……
}
驅動編寫示例 leddrv.c
- 配置M口M1引腳爲輸出口
#define rGPMCON *((volatile int *) 0x7f008820 )
void ledconfig()
tmp= rGPMCON; //讀出端口寄存器值
tmp &=! (0xF<<4); //把bit4~7清0
tmp |= (1<<4); //把bit4~7寫入0x1值
rGPMCON = tmp; //寫回到端口寄存器
}
- 點亮
配置M口M1輸出低電平
#define rGPMDAT *((volatile int *) 0x7f008824 )
void ledon()
{
tmp= rGPMDAT; //讀出端口寄存器值
tmp &=! (0x1<<1); //把bit1清0
tmp |= (0<<1); //把bit1寫入0x0值
rGPMDAT = tmp; //寫回到端口寄存器
}
- 熄滅
配置M口M1輸出高電平
void ledoff()
{
tmp= rGPMDAT; //讀出端口寄存器值
tmp &= ! (0x1<<1); //把bit1清0
tmp |= (1<<1); //把bit1寫入0x1值
rGPMDAT = tmp; //寫回到端口寄存器
}
課後作業
編寫一個在非操作系統LED燈閃爍的程序,要求
1)控制GPM2和GPM4端口;
2)寫出驅動程序和應用程序。
剛開始嵌入式,對於硬件方面有很多不理解,不過這不影響我編程。
答案如下:
- 驅動程序 leddrv.c
// leddrv.c
#define rGPMCON *((volatile int *) 0x7f008820 )
// 控制GPM2和GPM4端口
void ledconfig(){
tmp= rGPMCON; //讀出端口寄存器值
tmp &=! (0xF<<8); //把bit8~11清0
tmp |= (1<<8); //把bit8~11寫入0x1值
tmp &=! (0xF<<16); //把bit16~19清0
tmp |= (1<<16); //把bit16~19寫入0x1值
// 這裏再提供一種簡便寫法,完全等價上面四行、
// tmp &= !(0xF<<8 | 0xF<<16);
// tmp |== (1<<8 | 1 <<16);
rGPMCON = tmp; //寫回到端口寄存器
}
#define rGPMDAT *((volatile int *) 0x7f008824 )
void ledon()
{
tmp= rGPMDAT; //讀出端口寄存器值
tmp &= !(0x1<<2); //把bit2清0
tmp |= (0<<2); //把bit2寫入0x0值
tmp &= !(0x1<<4); //把bit4清0
tmp |= (0<<4); //把bit4寫入0x0值
// 這裏再提供一種簡便寫法,完全等價上面四行
// tmp &= !(0x1<<2 | 0x1<<4);
// tmp |= (0<<2 | 0<<4)
rGPMDAT = tmp; //寫回到端口寄存器
}
void ledoff()
{
tmp= rGPMDAT; //讀出端口寄存器值
tmp &= !(0x1<<2); //把bit2清0
tmp |= (1<<2); //把bit2寫入0x1值
tmp &= !(0x1<<4); //把bit4清0
tmp |= (1<<4); //把bit4寫入0x1值
// 這裏再提供一種簡便寫法,完全等價上面四行
// tmp &= !(0x1<<2 | 0x1<<4);
// tmp |= (1<<2 | 1<<4)
rGPMDAT = tmp; //寫回到端口寄存器
}
- 應用程序 ledapp.c
// leadapp.c
void delay(){ // 停止一段時間
for( i=0;i<1000;i++)
for( j=0;j<1000;j++);
}
void main()
{
ledconfig(); // 配置驅動
while(1)
{
ledon();delay();
ledoff();delay();
}
}