PIC18F46K22微控制器
所需的零件清單、示例程式碼:所需零件:
PIC18F46K22 微控制器
16MHz 晶振
22pF 綠色陶瓷電容 x2
10k 歐姆電阻 x2
10uF 25V 電解電容
1N4001 阻擋二極管
LED x2
220 歐姆電阻 x2
2x20 腳 LCD 顯示器
10k 歐姆可變電阻
按鈕開關 x4
杜邦線、面包板等
連接腳位:
PIC18F46K22
+---------+
| |
VSS|1 40|VDD
RA0|2 39|PGC
RA1|3 38|PGD
RA2|4 37|VSS
RA3|5 36|OSC1
RA4|6 35|OSC2
RA5|7 34|AN11
RC0|8 33|AN10
RC1|9 32|AN9
RC2|10 31|AN8
RC3|11 30|AN7
RC4|12 29|AN6
RC5|13 28|AN5
RC6|14 27|AN4
RC7|15 26|AN3
| |
+---------+
示例程式碼:
#include <xc.h>
#pragma config FOSC = INTIO67 // 內部振盪器
#pragma config PLLCFG = ON // PLL 開啟
#pragma config PRICLKEN = OFF // 主時鐘開啟
#pragma config PWRTEN = ON // 電源上電延遲
#pragma config BOREN = OFF // 無須 Brown-out 检测
#pragma config BORV = 190 // Brown-out 電壓設為 1.9V
#pragma config WDTEN = OFF // 看門狗定時器關閉
#pragma config CCP2MX = PORTC // CCP2 輸出映射到 C3
#define _XTAL_FREQ 16000000 // 頻率 16MHz
void main() {
// 設置 GPIO 方向
TRISC = 0b00000000; // C 腳位設置為輸出模式
LATC = 0b00000000; // 將 C 腳位拉低
// 初始化 LCD 顯示器
lcd_init();
// 顯示訊息
lcd_puts("Hello World!");
while (1) {
// 讀取按鈕開關狀態
if (PORTAbits.RA0 == 1) { // 如果按鈕1被按下
LATCbits.LC0 = 1; // C0 腳位為高電位,LED亮
lcd_clear(); // 清空 LCD 顯示器
lcd_puts("Button 1"); // 顯示訊息
} else {
LATCbits.LC0 = 0; // C0 腳位為低電位,LED滅
}
if (PORTAbits.RA1 == 1) { // 如果按鈕2被按下
LATCbits.LC1 = 1; // C1 腳位為高電位,LED亮
lcd_clear(); // 清空 LCD 顯示器
lcd_puts("Button 2"); // 顯示訊息
} else {
LATCbits.LC1 = 0; // C1 腳位為低電位,LED滅
}
if (PORTAbits.RA2 == 1) { // 如果按鈕3被按下
LATCbits.LC2 = 1; // C2 腳位為高電位,LED亮
lcd_clear(); // 清空 LCD 顯示器
lcd_puts("Button 3"); // 顯示訊息
} else {
LATCbits.LC2 = 0; // C2 腳位為低電位,LED滅
}
if (PORTAbits.RA3 == 1) { // 如果按鈕4被按下
LATCbits.LC3 = 1; // C3 腳位為高電位,LED亮
lcd_clear(); // 清空 LCD 顯示器
lcd_puts("Button 4"); // 顯示訊息
} else {
LATCbits.LC3 = 0; // C3 腳位為低電位,LED滅
}
}
}
// 初始化 LCD 顯示器
void lcd_init() {
// 設置 LCD 顯示器腳位為輸出模式
TRISD = 0b00000000;
// 初始設置
LATD = 0b00110000;
__delay_ms(10);
LATD = 0b00110000;
__delay_ms(10);
LATD = 0b00110000;
__delay_ms(10);
LATD = 0b00100000;
__delay_ms(10);
lcd_cmd(0b00101000); // 4 位元、2 行、5x8 點
lcd_cmd(0b00001000); // 顯示器和游標關閉
lcd_cmd(0b00000001); // 顯示器清屏
lcd_cmd(0b00000110); // 游標右移
lcd_cmd(0b00001100); // 顯示
// 寫入指令到 LCD 顯示器
void lcd_cmd(unsigned char cmd) {
LATD = (cmd >> 4) & 0x0F; // 寫入高位元
LATDbits.LD7 = 0; // RS 腳位為低電位,選擇指令模式
LATDbits.LD6 = 0; // RW 腳位為低電位,選擇寫入模式
LATDbits.LD5 = 1; // E 腳位為高電位,啟動 LCD 顯示器
__delay_us(10); // 等待一段時間
LATDbits.LD5 = 0; // E 腳位為低電位,關閉 LCD 顯示器
__delay_us(10); // 等待一段時間
LATD = cmd & 0x0F; // 寫入低位元
LATDbits.LD5 = 1; // E 腳位為高電位,啟動 LCD 顯示器
__delay_us(10); // 等待一段時間
LATDbits.LD5 = 0; // E 腳位為低電位,關閉 LCD 顯示器
__delay_ms(5); // 等待一段時間
}
// 寫入字元到 LCD 顯示器
void lcd_putc(unsigned char c) {
LATD = (c >> 4) & 0x0F; // 寫入高位元
LATDbits.LD7 = 1; // RS 腳位為高電位,選擇資料模式
LATDbits.LD6 = 0; // RW 腳位為低電位,選擇寫入模式
LATDbits.LD5 = 1; // E 腳位為高電位,啟動 LCD 顯示器
__delay_us(10); // 等待一段時間
LATDbits.LD5 = 0; // E 腳位為低電位,關閉 LCD 顯示器
__delay_us(10); // 等待一段時間
LATD = c & 0x0F; // 寫入低位元
LATDbits.LD5 = 1; // E 腳位為高電位,啟動 LCD 顯示器
__delay_us(10); // 等待一段時間
LATDbits.LD5 = 0; // E 腳位為低電位,關閉 LCD 顯示器
__delay_ms(5); // 等待一段時間
}
// 寫入字串到 LCD 顯示器
void lcd_puts(const char* s) {
while (*s) {
lcd_putc(*s++);
}
}
// 主程式
void main(void) {
// 設定 I/O 腳位
TRISD = 0x00; // 設定 PORTD 為輸出
TRISEbits.RE0 = 1; // 設定 RE0 為輸入
ANSELEbits.ANSE0 = 0; // 設定 RE0 為數位腳位
// 初始化 LCD 顯示器
lcd_init();
while (1) {
// 讀取 RE0 腳位的狀態
if (PORTEbits.RE0 == 1) {
lcd_cmd(0x01); // 清除顯示器
lcd_puts("Button Pressed");
} else {
lcd_cmd(0x01); // 清除顯示器
lcd_puts("Button Not Pressed");
}
scss
Copy code
__delay_ms(500); // 等待一段時間
}
}
// 函式:LCD 初始化
void lcd_init(void) {
lcd_cmd(0x02); // 回到 Home 狀態
lcd_cmd(0x28); // 設定 4-bit 模式,2 行顯示,5x7 字元大小
lcd_cmd(0x0C); // 顯示器 ON,游標不閃爍
lcd_cmd(0x06); // 游標右移
lcd_cmd(0x01); // 清除顯示器
__delay_ms(2); // 等待 LCD 完成命令
}
// 函式:傳送命令到 LCD
void lcd_cmd(unsigned char command) {
// 傳送上半個 Byte
PORTD &= 0x0F; // 清除上半個 Byte
PORTD |= (command & 0xF0); // 寫入上半個 Byte
PORTDbits.RD2 = 0; // RS 腳位設為命令模式
PORTDbits.RD3 = 1; // 使能腳位設為高
__delay_us(1); // 等待一段時間
PORTDbits.RD3 = 0; // 使能腳位設為低
__delay_us(100); // 等待一段時間
// 傳送下半個 Byte
PORTD &= 0x0F; // 清除上半個 Byte
PORTD |= ((command << 4) & 0xF0); // 寫入下半個 Byte
PORTDbits.RD2 = 0; // RS 腳位設為命令模式
PORTDbits.RD3 = 1; // 使能腳位設為高
__delay_us(1); // 等待一段時間
PORTDbits.RD3 = 0; // 使能腳位設為低
__delay_us(100); // 等待一段時間
}
// 函式:傳送資料到 LCD
void lcd_putc(unsigned char data) {
// 傳送上半個 Byte
PORTD &= 0x0F; // 清除上半個 Byte
PORTD |= (data & 0xF0); // 寫入上半個 Byte
PORTDbits.RD2 = 1; // RS 腳位設為資料模式
PORTDbits.RD3 = 1; // 使能腳位設為高
__delay_us(1); // 等待一段時間
PORTDbits.RD3 = 0; // 使能腳位設為低
__delay_us(100); // 等待一段時間
// 傳送下半個 Byte
PORTD &= 0x0F; // 清除
PORTD |= ((data << 4) & 0xF0); // 寫入下半個 Byte
PORTDbits.RD2 = 1; // RS 腳位設為資料模式
PORTDbits.RD3 = 1; // 使能腳位設為高
__delay_us(1); // 等待一段時間
PORTDbits.RD3 = 0; // 使能腳位設為低
__delay_us(100); // 等待一段時間
}
// 函式:設定游標位置
void lcd_set_cursor(unsigned char row, unsigned char col) {
// 計算游標位置
unsigned char pos;
if (row == 1) {
pos = 0x80 + col - 1;
} else if (row == 2) {
pos = 0xC0 + col - 1;
} else if (row == 3) {
pos = 0x94 + col - 1;
} else if (row == 4) {
pos = 0xD4 + col - 1;
}
// 傳送設定命令
lcd_cmd(pos);
}
// 函式:顯示字串
void lcd_puts(unsigned char row, unsigned char col, const char *str) {
lcd_set_cursor(row, col); // 設定游標位置
// 逐一顯示字元
while (*str != '\0') {
lcd_putc(*str++);
}
}
// 主程式
void main() {
// 初始化 LCD
lcd_init();
// 顯示文字
lcd_puts(1, 1, "Hello World!");
}
以上就是一個簡單的 LCD 顯示程式,可以顯示「Hello World!」字串在 LCD 上。
頁:
[1]