?? iopic18.c
字號:
// 將指定棋盤格子(含格式內的棋子)反相顯示
// (當選定待移動棋子但未走動時,通過反復反相顯示形成閃爍效果)
//-----------------------------------------------------------------
void panel_invert(BYTE loc[], BYTE flag)
{
BYTE char_code;
//文本區首地址為0x2000,每個棋盤格子由4x4=16個字符(16字節)鋪成,
//每行有8列棋盤格子,占16x8=128字節.
//下面的語句根據位置loc得到平鋪指定格子底色的字符在DDRAM中的起始地址
WORD addr = 0x2000 + loc[0] * 128 + loc[1] * 4;
//偶數行奇數列,奇數行偶數列為黑格子,否則為白格子(& 0x01可得到1/0[奇/偶])
if ((loc[0] & 0x01) ^ (loc[1] & 0x01))
{ //黑格子反相(flag為1)時用編碼為0x00的字符鋪底
//否則(flag為0)還原時用編碼為0x80的自定義字符"■"鋪底
char_code = flag ? 0x00 : 0x80;
}
else
{ //白格子反相(flag為1)時用編碼為0x80的自定義字符"■"鋪底
//否則(flag為0)還原時用編碼為0x00的內置字符(無色)鋪底
char_code = flag ? 0x80 : 0x00;
}
//用編碼為0x00或0x80的全白或全黑字符重新對指定格子鋪底色
//每個格子需要鋪4行字符
for (INT i = 0; i < 4; i++)
{ //設置顯示DDRAM地址
lcd_wrcmd2(LCD_ADDRESS, addr);
//每行鋪4個編碼為0x00或0x80的字符
for (INT j = 0; j < 4; j++) lcd_wrcmd1(LCD_WRITEINC, char_code);
//鋪完一行后,addr指向下一行的DDRAM地址
//(由于棋盤每格有4列字符,共8列,故定位到下一行同一列的地址需要+32)
//(該值與所設置的文本區寬度:LCD_TEXTAREA,32也相對應)
addr += 32;
}
}
//-----------------------------------------------------------------
// 檢測液晶狀態寄存器(STA0~STA7)
//-----------------------------------------------------------------
void lcd_status_check(BYTE STA_mask)
{
BYTE status; TRISD = 0xFF; //PORTD設為輸入,讀取狀態寄存器
do
{ //發送讀狀態寄存器字節命令
PORTA = LCD_STATUS; asm("nop");
//從PORTD讀取狀態寄存器字節,保存到status變量
//隨后禁止LCD操作(禁止讀/寫,禁止片選,C/D設為1)
status = PORTD; PORTA = LCD_DONE;
//與掩碼相與時為0x00則繼續讀狀態
} while ((status & STA_mask) == 0x00);
}
//-----------------------------------------------------------------
// LCD清屏
//-----------------------------------------------------------------
void lcd_cls()
{
lcd_wrcmd(LCD_DISPLAY + 0x00); //關閉顯示
lcd_wrcmd2(LCD_ADDRESS, 0x0000); //LCD RAM地址指針設為0x0000
lcd_wrcmd(LCD_AUTOWRITE); //發送數據自動寫命令(RAM地址自動遞增)
for (INT i = 0; i < 0x2400; i++) //
{
lcd_status_check(0x08); //數據自動寫就緒(DAWRDY)標志位為0則等待
PORTD = 0x00; TRISD = 0x00; //向PORTD端口寫全0
PORTA = LCD_DATA; //在PORTA端口使能寫數據(C/D=0,WR=0,CE=0,RD=1)
PORTA = LCD_DONE; //完成后禁止操作
}
lcd_wrcmd(LCD_AUTORESET); //自動讀/寫復位(退出自動讀/寫方式)
lcd_wrcmd(LCD_DISPLAY + 0x0C); //設置顯示模式(啟用圖形/文本顯示)
}
//-----------------------------------------------------------------
// 將img指針所指向的棋子圖形點陣數據中的num個字節寫入LCD的addr地址顯示
//-----------------------------------------------------------------
void lcd_blit(WORD addr, const BYTE *img, BYTE num)
{
lcd_wrcmd2(LCD_ADDRESS,addr);//設置顯示DDRAM地址為addr
lcd_wrcmd(LCD_AUTOWRITE); //設置自動寫(DDRAM地址自動遞增)
while (num--) //共發送num個字節
{
lcd_status_check(0x08); //檢測LCD狀態寄存器中的STA3,等待自動寫就緒
//向PORTD端口輸出顯示字節
PORTD = *img++; TRISD = 0;
//PORTA端口使能寫后結束操作
PORTA = LCD_DATA; PORTA = LCD_DONE;
}
lcd_wrcmd(LCD_AUTORESET); //自動寫復位(停止自動寫)
}
//-----------------------------------------------------------------
// 寫無參數LCD命令
//-----------------------------------------------------------------
void lcd_wrcmd(BYTE cmd)
{
lcd_status_check(0x01); //檢測LCD狀態寄存器中的STA0,等待指令讀寫狀態位就緒
PORTD = cmd; TRISD = 0; //命令字節送PORTD端口
PORTA = LCD_COMMAND; //寫命令
PORTA = LCD_DONE; //禁止操作
}
//-----------------------------------------------------------------
// 寫帶單字節參數的LCD命令
//-----------------------------------------------------------------
void lcd_wrcmd1(BYTE cmd, BYTE data)
{
lcd_status_check(0x02); //檢測LCD狀態寄存器中的STA1,等待數據讀寫狀態位就緒
PORTD = data; TRISD = 0x00; //參數送PORTD端口
PORTA = LCD_DATA; //寫參數數據
PORTA = LCD_DONE; //禁止操作
lcd_status_check(0x01); //檢測LCD狀態寄存器中的STA0,等待指令讀寫狀態位就緒
PORTD = cmd; TRISD = 0x00; //命令字節送PORTD端口
PORTA = LCD_COMMAND; //寫命令
PORTA = LCD_DONE; //禁止操作
}
//-----------------------------------------------------------------
// 寫帶字參數(兩字節)LCD命令
//-----------------------------------------------------------------
void lcd_wrcmd2 (BYTE cmd, WORD arg)
{
lcd_status_check(0x02); //檢測LCD狀態寄存器中的STA1,等待數據讀寫狀態位就緒
PORTD = arg & 0xFF;TRISD = 0x00; //參數D1送PORTD端口
PORTA = LCD_DATA; //寫參數數據D1
PORTA = LCD_DONE; //禁止操作
lcd_status_check(0x02); //檢測LCD狀態寄存器中的STA1,等待數據讀寫狀態位就緒
PORTD = arg >> 8; TRISD = 0x00; //參數D2送PORTD端口
PORTA = LCD_DATA; //寫參數數據D2
PORTA = LCD_DONE; //禁止操作
lcd_status_check(0x01); //檢測LCD狀態寄存器中的STA0,等待指令讀寫狀態位就緒
PORTD = cmd; TRISD = 0x00; //命令字節送PORTD端口
PORTA = LCD_COMMAND; //寫命令
PORTA = LCD_DONE; //禁止操作
}
//-----------------------------------------------------------------
// 輸出提示音,提示yourmove
//-----------------------------------------------------------------
void sound_yourmove()
{
tone(100, 100);
}
//-----------------------------------------------------------------
// 棋子被捕獲時所輸出的聲音
//-----------------------------------------------------------------
void sound_capture()
{
tone(50, 100); tone(75, 75); tone(100, 50); sleep(200);
}
//-----------------------------------------------------------------
// 棋子無效移動時所輸出的聲音
//-----------------------------------------------------------------
void sound_illegal()
{
tone(400, 100);
}
//-----------------------------------------------------------------
// 通過T0定時器,按指定周期和時長輸出聲音
//-----------------------------------------------------------------
void tone(WORD period, WORD cycles)
{
LATC = 0x03; //RC0,RC1初始輸出11(0x03)
T0CON = 0x04; //T0定時器關,設16位模式,1/32分頻
while (cycles--)
{
TMR0H = -period >> 8; //設置TMR0定時初值
TMR0L = -period & 0xFF;
TMR0IF = 0; //中斷標志位請0
TMR0ON = 1; //啟動定時器
while (TMR0IF == 0); //等待T0溢出
TMR0ON = 0; //停止定時器
LATC ^= 0x03; //RC0,RC1兩腳輸出11,00,11,00,驅動揚聲器輸出
}
}
//-----------------------------------------------------------------
// 按鍵掃描函數,無鍵按下時返回0xFF
//-----------------------------------------------------------------
BYTE scankeypad()
{
BYTE r,c,tmp,key = 0xFF;
//掃描8x8按鍵矩陣(相當于本例的觸摸屏的8x8=64個格子)
for (c = 0; c < 8; c++)
{ //在相應的列上設置低電平,然后讀取行狀態tmp
//由于使用了3-8譯碼器,輸出000~111時
//實際輸出的列字節為111111110,11111101,...01111111(僅有一位為0)
PORTE = c; sleep(1); tmp = PORTB;
//查看變為低電平的行,根據行號r與列號c,得出當前按鍵序號(0~63)
for (r = 0; r < 8; ++r)
{
if ((tmp & (1 << r)) == 0) { key = r * 8 + c; goto done; }
}
}
done: return key;
}
//-----------------------------------------------------------------
// 睡眠函數
//-----------------------------------------------------------------
void sleep(INT msecs)
{
while (msecs--)
{
TMR0L = -32; //設置TMR0定時初值
TMR0IF = 0; //TMR0溢出中斷標志位清0
T0CON = 0xC6; //T0定時器設為8位模式(T08BIT),啟動(TMR0ON)
while (TMR0IF == 0); //等待定時器溢出
TMR0ON = 0; //定時器關
}
}
//-----------------------------------------------------------------
// 字符輸出函數
//-----------------------------------------------------------------
void putch(char value)
{
if (value == '\n') value = '\r';
TXREG = value; while (!TRMT);//向串口輸出一字節,等待發送結束
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -