本文最后更新于 2024年1月27日 下午
PIC16F系列单片机接口程序设计经典案例
针对Brunel University:2021 EE2623 Computer Architecture and
Interfacing 的期末复习笔记
Lecturer: Dr. Itagaki Takebumi(板垣 剛文)/Dr.Hongying
Meng(孟鸿鹰)
程序仅包含主函数部分。
输入接口
简单开关
1 2 3 4 5 6 7 8 9 10 11
| while(1) { if((porta&1)==0) { delay(5); if((porta&1)==0) { ... } } }
|
键盘
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| void main() { adcon1 = 0x06; trisa = 11110000b; porta = 0xff; while(1) { clear_bit(porta,0); if((porta&0x10)==0) { value = '1'; } if((porta&0x20)==0) { value = '2'; } if((porta&0x40)==0) { value = '3'; } set_bit(porta,0); clear_bit(porta,1); if((porta&0x10)==0) { value = '4'; } if((porta&0x20)==0) { value = '5'; } if((porta&0x40)==0) { value = '6'; } ... } }
|
显示接口
LED
闪烁LED
1 2 3 4 5 6 7 8 9 10
| void main() { trisb = 0; while(1) { portb = 0xff; delay(10); portb = 0; } }
|
流水灯
1 2 3 4 5 6 7 8 9
| void main() { trisb = 0; while(1) { portb = portb << 1; delay(10); } }
|
八位数码管
一位数字显示
1 2 3 4 5 6 7
| char seg8(char value) { if(value == 0) return(0xc0); if(value == 1) return(0xf9); ... if(value > 9) return(0xff); }
|
四位数显示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| void display(int value) { portb = seg8(value / 1000); set_bit(porta,3); delay(4); value = value % 1000; clear_bit(porta,3); portb = seg8(value / 100); set_bit(porta,2); delay(4); value = value % 100; clear_bit(porta,1); portb = seg8(value / 10); set_bit(porta,1); delay(4); value = value % 100; clear_bit(porta,2); portb = seg(value % 10); set_bit(porta,0); delay(4); clear_bit(porta,0); }
|
LCD
初始化
1 2 3 4 5 6 7 8 9 10 11
| void lcd_init() { delay(10); portb = 0x23; portb = 0x03; delay(10); portb = 0x23; portb = 0x03;
}
|
发送指令
1 2 3 4 5 6 7
| void lcd_cmd(char cmd) { portb = 0x20+((cmd>>4)&0x0f); portb = (cmd>>4)&0x0f; portb = 0x20+(cmd&0x0f); portb = cmd & 0x0f; }
|
发送单个字符
1 2 3 4 5 6 7
| void lcd_char(char c) { portb = 0x30 + ((c>>4)&0x0f); portb = 0x10 + ((c>>4)&0x0f); portb = 0x30 + (c&0x0f); portb = 0x10 + (c&0x0f); }
|
显示字符串
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| void display_message(const char* message) { int i = 0; while(message[i] != 0) { lcd_char(message[i]); i++; } } void main() { adcon1 = 0x06; trisa = 0xf8; trisb = 0x00; lcd_cmd(1); lcd_init(); lcd_cmd(0x38); lcd_cmd(0x0c); lcd_cmd(0x06); lcd_cmd(1); while(1) { lcd_cmd(0x80); display_massage("Hello"); lcd_cmd(0xc0); display_message("world"); } }
|
LCD在显示数字时,一定要将数字转换为ASCII码,具体操作为:display_char('0'+number);
数模转换器 ADC
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| void convert(char channel) { adcon0 = 11000001b + (channel<<3); set_bit(adcon0, GODONE); while((adcon0 & 00000100b) !=0); return((adresh<<8)+adresl); } void main() { int value; adcon1 = 0x80; adcon0 = 11000001b; while(1) { value = covnert(4); } }
|
计时器
延迟函数(通用)
1 2 3 4 5 6 7 8
| void delay(int j) { int i; for(; j!=0; j--) { for(i=8333; i!=0; i--); } }
|
利用溢出设置延迟
1 2 3 4 5 6 7 8 9 10 11 12
| void delay(int x) { tmr0 = 0; clear_bit(intcon,TOIF); while(x!=0) { while((intcon & 00000100b) == 0); clear_bit(intcon, T0IF); x--; }
}
|
如果Fosc/4=0.2s, Pre-scalar=1:32,x=61时,能造成
0.2x32x256usx61=0.0999424s的延迟
中断程序
中断程序的时间控制
1 2 3 4 5 6
| void interrupt() { clear_bit(intcon,T0IF); tmr0 = 100; ··· }
|
PWM 控制马达
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| TMR0 = 246; int cycle; int pwm = 400; void interrupt() { cycle--; if(cycle == 0) { cycle = 1000; } if(pwm == 0) { pulse = 0; clear_bit(portb,7); } else { pulse = pwm; set_bit(portb,7); } else { if(pulse != 0) { pulse--; } if(pulse == 0) { clear_bit(portb,7); } } }
|