第4章
I/O埠基本輸入輸出控制
基本輸入輸出控制
LED
7段顯示器
指撥開關
按鈕開關
四位數7段顯示器多工掃描
文字型LCD
I/O 埠結構圖
埠結構圖(輸出)
埠結構圖(下拉輸入)
埠結構圖(上拉輸入)
A 埠相關的暫存器
P_IOA_Dir(讀/寫)($7002H ) A 埠的方向暫存器
P_IOA_Attrib(讀/寫)($7003H) A 埠的屬性暫存器
P_IOA_Data(讀/寫)($7000H) A 埠的資料暫存器
P_IOA_Buffer (讀/寫) ($7001H) A 埠的緩衝暫存器
P_IOA_Latch(讀)($7004H) A 埠的栓鎖暫存器
B 埠相關的暫存器
P_IOB_Dir(讀/寫)($7007H ) B 埠的方向暫存器
P_IOB_Attrib(讀/寫)($7008H) B 埠的屬性暫存器
P_IOB_Data(讀/寫)($7005H) B 埠的資料暫存器
P_IOB_Buffer (讀/寫) ($7006H) B 埠的緩衝暫存器
P_IOA_Data 與 P_IOA_Buffer 區別
讀取 IO 埠 從埠讀取資料的兩種方式:從 P_IOA_Data 讀取資料相 當於讀取埠接腳的訊號。 然而,從 P_IOA_Buffer 讀取 資料相當於從資料暫存器中讀取資料。
data = *P_IOA_Buffer//從 A 埠資料暫存器中讀取資料
data = *P_IOA_Data //從 A 埠接腳讀取資料
寫入 IO 埠 這裏有兩種寫入IOA 資料的方法,向 P_IOA_Data 寫入 資料結果等於向 P_IOA_Buffer 寫入資料。
data = 0x0000;
*P_IOA_Data = data ;//寫資料到 P_IOA_Data
I/O 埠的組合控制設定
具資料反相器的低電位輸 出
低電位輸出(帶資料反相 否 器)
1 0
1
具資料反相器的高電位輸 出
高電位輸出(帶資料反相 否 0 器)
0 1
懸浮式輸入接腳 否
1 懸浮 1
0
懸浮式輸入接腳 是
0 懸浮 1
0
具上拉電阻的輸入接腳 是
1 上拉 0
0
具下拉電阻的輸入接腳 是
0 下拉 0
0
功能描述 是否具
喚醒功能 Data 功能
Attribution Direction
規劃IO埠
規劃IOA[3~0] 為具下拉電阻的輸入埠,IOA[7~4]為具上拉電阻的輸入埠,
IOA[11~8]為具資料暫存器的高電位輸出埠,
IOA[15~12] 為具資料暫存器的低電位輸出埠
解:*P_IOA_Dir = 0xFF00;
*P_IOA_Attrib = 0xFF00;
*P_IOA_Data = 0x0FF0;
B埠的特殊功能
IOB3設為輸入狀態 外部中斷源(負緣觸發)
EXT2 IOB3
IOB2 為反相輸出方式 與 IOB4 組成一個 RC
反饋電路 Feedback_Output1
IOB2設為輸入狀態 外部中斷源(負緣觸發)
EXT1 IOB2
SIO 的資料訊號 SDA
IOB1
SIO 的時脈訊號 SCK
IOB0
備註 功能描述
特殊功能 腳位
B埠的特殊功能 (cont.)
參考UART介面部分 UART 發送埠
Tx IOB10
參考計時器/計數器 部分
TimerB PWM 脈寬調變輸 出
BPWMO IOB9
參考計時器/計數器 部分
TimerA PWM 脈寬調變輸 出
APWMO IOB8
參考UART介面部分 UART 接收埠
Rx IOB7
備註 功能描述
特殊功能 腳位
LED與指撥開關線路圖
規劃B Port為同相低電位輸出
*P_IOB_Dir=0xffff;
*P_IOB_Attrib=0xffff;
*P_IOB_Data=0x0000 ;
規劃B Port為反相的低電位輸出
*P_IOB_Dir = 0xffff;
*P_IOB_Attrib = 0x0000;
*P_IOB_Data = 0;
規劃 A Port 為具下拉電阻輸入
*P_IOA_Dir = 0x0000;
*P_IOA_Attrib = 0x0000;
*P_IOA_Data = 0x0000;
LED閃爍(B Port)
#include "SPCE061A.H"
int main() {
//規劃BPort為同相低電位輸出
*P_IOB_Dir=0xffff;
*P_IOB_Attrib=0xffff;
*P_IOB_Data=0x0000; //IO初始化完成 while (1) {
*P_IOB_Data=0xff00; //IOB Port 亮
*P_IOB_Data=0xffff; // IOB Port 滅
IDE 模擬操作(Simulator)
延遲副程式
void delay(int n) {
int i;
for (i=0; i<n; i++) ;
*P_Watchdog_Clear = 0x0001;
}
延遲副程式(delay_ms)
void delay_ms(int n) {
int i,j;
for (i = 0; i < n; i++ )
for (j = 0; j < 33 ; j++)
//用示波器量*P_Watchdog_Clear = 0x0001;
//清除看門狗計數器
}
LED閃爍(B Port)2
#include "SPCE061A.H"
int main()
{ //規劃BPort為同相低電位輸出
*P_IOB_Dir=0xffff;
*P_IOB_Attrib=0xffff;
*P_IOB_Data=0x0000; //IO初始化完成 while (1) {
*P_IOB_Data=0xff00; //IOB Port 亮 delay_ms(500); // 0.5 秒
*P_IOB_Data=0xffff; // IOB Port 滅 delay_ms(500);
61開發板
61實驗箱
上機操作(ICE)
將下載線一邊接電腦Print Port,另外一邊 接開發板(61板)或實驗箱(61箱)
調整Jump
接上61板或實驗箱(61箱)電源
IOA 輸入 IOB輸出
void Init_A_Port()
{ //規劃 A Port 為具下拉電阻輸入
*P_IOA_Dir = 0x0000;
*P_IOA_Attrib = 0x0000;
*P_IOA_Data = 0x0000;
}
void Init_B_Port()
{ // B Port為同相低電位輸出
*P_IOB_Dir = 0xffff;
*P_IOB_Attrib = 0xffff;
程式架構
#include “spce061a.h”
void Init_A_Port();
void Init_B_Port();
void delay_ms( int );
void main()
{ Init_A_Port();
Init_B_Port();
...
}
void Init_A_Port() { ...}
void Init_B_Port() { ... } void delay_ms() { ... }
LED單燈左移
int main() {
int i;
char
table[8]={0xFFFE,0xFFFD,0xFFFB,0xFFF7,0xFFEF,0xF FDF,0xFFBF,0xFF7F};
Init_B_Port(); //規劃 B Port 為同相低電位輸出 while (1)
for (i =0; i < 8; i++) {
*P_IOB_Data = table[i];
指撥開關(IOA輸入 IOB輸出)
while (1) {
key = *P_IOA_Data;
key &= 0x00ff;
*P_IOB_Data = key;
}
清除看門狗計數器 內定約0.75秒自動系統重置
*P_Watchdog_Clear = 0x0001;
LED花樣變化
1.
B PORT 向左步步高昇(8個LED)2.
B PORT 向左步步高昇(8個LED)又遞減3.
B PORT由兩側向中間亮(8個LED)4.
B PORT由中間向兩側亮(8個LED)5.
B PORT由兩側向中間亮再中間向兩側亮(8個LED)6.
B PORT奇數LED同時亮,再來偶數LED同時亮,輪流交替(8個LED)
7.
B PORT LED左移二回後右移五回,重複輪流(8個 LED)掃描按鍵(消除開關彈跳)
unsigned int KeyScan(void) { unsigned int Data;
unsigned int Temp;
Data = *P_IOA_Data; //讀取IOA埠輸入 Data = Data&0x000f; //僅取低4位有效值
if(Data!=0) //非零則表示有鍵按下
{
Delay(); //延時消除彈跳(消除抖動)
Temp = *P_IOA_Data;
Temp = Temp&0x000f; //僅取低4位有效值 if(Data != Temp) Data = 0;
//兩次讀數不相等,則置返回值為0,表示不穩定 }
開關彈跳Delay
void Delay(void) {
unsigned int Count;
for ( Count = 0; Count <= 3000; Count++ )
*P_Watchdog_Clear = 0x0001;
//清看門狗
}
掃描按鍵(消除開關彈跳)2
unsigned int KeyScan(void) {
unsigned int Data;
unsigned int Temp;
Data = *P_IOA_Data; //讀取IOA埠輸入 Data = Data & 0x000f; //僅取低4位有效值 delay(10000); //延時去彈跳
*P_Watchdog_Clear = 0x0001; //清看門狗 return Data; //返回鍵值
}
暫停單燈左移1
int main() {
unsigned int a,key,state=1,i=0;
Init_A_Port(); //規劃 A Port 為帶下拉電阻輸入 Init_B_Port(); //規劃 B Port 為同相低電位輸出 while (1)
{
key = *P_IOA_Data; //讀取 A Port值 key &= 0x000f; //保留右邊 4 bit delay(10000); // 影響靈敏度
if ( key == 0x0001 )
if (state ==1 ) state = 0;
else state = 1;
if (state == 1) {
*P_IOB_Data = table[i++];
if ( i == 8 ) i=0;
} }
暫停單燈左移2
int main()
{ unsigned int a,key,i=0;
Init_A_Port(); //規劃 A Port 為帶下拉電阻輸入 Init_B_Port(); //規劃 B Port 為同相低電位輸出 while (1)
{
key = KeyScan();
if (key != 0)
if (state == 1) state = 0; else state = 1;
if (state == 1) {
*P_IOB_Data = table[i++];
if ( i == 8 ) i=0;
delay_ms(500);
七段顯示器示意圖
七段顯示器接線圖
0~9往上數
#include "SPCE061a.H"
char
TABLE[10]={0xFFC0,0xFFF9,0xFFA4,0xFFB0,0xFF99,0xFF9 2,0xFF82,0xFFF8,0xFF80,0xFF90}; //共陽
int main() { int i;
Init_B_Port(); //規劃 B Port 為同相低電位輸出 while (1)
for (i = 0; i < 10; i++ ) {
*P_IOB_Data = TABLE[i];
delay_ms(500);
} }
四位數七段顯示器
方法一:4顆七段
優點:程式容易撰寫
缺點:共須4*9=36隻接腳,消耗電流大 方法二: 4顆七段(多工掃描)
優點:共須4+8=12隻接腳,消耗電流小
缺點:程式較困難,自已送出字型碼 方法三: 4顆七段(多工掃描)加7447
優點:共須4+4=8隻接腳,消耗電流小四位數七段顯示器線路圖
共陽四位數七段正視圖
顯示5678
*P_IOB_Data = 0x00E8;
//個位數 *P_IOB_Data = 0x00D7;
//十位數 *P_IOB_Data = 0x00B6;
//百位數 *P_IOB_Data = 0x0075;
//千位數 E=1110
D=1101
B=1011
7=0111
LCD模組
文字型:2*20, 2*16,4*20(列行)
繪圖型:128*64, 320*240,1024*68
LCD內部方塊圖
規劃命令
寫入命令副程式
void LCD_Cmd(unsigned char cmd) {
*P_IOA_Data =0x8000 ;
// En=1, RW=0, RS=0 write command
*P_IOB_Data = cmd;
// control word
delay(2); // delay
*P_IOA_Data =0x0000;
// E=0; 禁能 LCD
}寫入資料副程式
void LCD_SendData(unsigned char data) {
*P_IOA_Data =0xA000 ;
// En=1, RW=0, RS=1 write data
*P_IOB_Data = data; // data word delay(2); // delay
*P_IOA_Data =0x2000; // E=0; 禁能 LCD
}
delay副程式
void delay(int n) {
int i;
for (i=0; i<n; i++) ;
*P_Watchdog_Clear = 0x0001;
}
清除顯示幕副程式
void LCD_Clear_Display() // 清除 顯示幕
{
LCD_Cmd(0x0001);
}
游標回原位副程式
void LCD_Cursor_Home() {
LCD_Cmd(0x0002);
}
DD RAM +1,顯示幕不移
void LCD_Entry_Mode_Right() {
LCD_Cmd(0x0006);
}
DD RAM -1,顯示幕不移
void LCD_Entry_Mode_Left() {
LCD_Cmd(0x0004);
}
顯示幕ON, 要游標且閃爍
void
LCD_Display_On_Cursor_ON_NOBlink(){
LCD_Cmd(0x000E);
}
顯示幕ON, 不要游標
void LCD_Display_On_Cursor_Off {
LCD_Cmd(0x000C);
}
顯示幕OFF
void LCD_Display_Off() {
LCD_Cmd(0x0008);
}
顯示幕右移
void LCD_Display_Shift_Right() {
LCD_Cmd(0x001C);
}
顯示幕左移
void LCD_Display_Shift_Left() {
LCD_Cmd(0x0018);
}
游標右移
void LCD_Cursor_Shift_Right() {
LCD_Cmd(0x0014);
}
游標左移
void LCD_Cursor_Shift_Left() {
LCD_Cmd(0x0010);
}
8 bit傳輸,顯示2行,5*7字型
void LCD_Function_Set() {
LCD_Cmd(0x0038);
}
設定游標位置 (0~1, 0~19)
void LCD_GotoXY(int row,int col) {
if (row == 0)
LCD_Cmd(0x0080+col);
else LCD_Cmd(0x00C0+col);
}
LCD_Reset()
void LCD_Reset() {
LCD_Function_Set(); // 8 bit傳輸,顯示2行,5*7 字型
delay(20000);
LCD_Display_Off(); // 顯示幕OFF LCD_Display_On_Cursor_Off();
// 顯示幕ON,不顯示游標,游標不閃爍 LCD_Entry_Mode_Right();
// 顯示完游標右移,游標移位禁能
LCD_Clear_Display(); // 清除顯示幕
LCD_Reset副程式
void LCD_Reset() {
LCD_Function_Set();
// 8 bit傳輸,顯示2行,5*7字型 delay(20000);
LCD_Display_Off(); // 顯示幕OFF LCD_Display_On_Cursor_Off(); // 顯示幕 ON,不顯示游標,游標不閃爍
LCD_Entry_Mode_Right();
// 顯示完游標右移,游標移位禁能
LCD_Clear_Display(); // 清除顯示幕