前の記事のとおりPIC12F675でI2C通信ができるようになりましたので、秋月電子で販売しているI2C LCD AQM0802Aに文字を表示するテストをします。
回路図です。AQM0802Aは、モジュールを使用しますので、プルアップ抵抗は内蔵しています。電源は電池2本です。
AQM0802Aの初期化の手順です。
プログラムです。
--------------------------------------
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
/* PIC12F675--AQM0802A
* GP4--SCL
* GP5--SDA
*/
* GP4--SCL
* GP5--SDA
*/
// CONFIG
#pragma config FOSC = INTRCIO // Internal OSC 4MHz
#pragma config WDTE = OFF
#pragma config PWRTE = ON
#pragma config MCLRE = OFF
#pragma config BOREN = OFF
#pragma config CP = OFF
#pragma config CPD = OFF
#pragma config FOSC = INTRCIO // Internal OSC 4MHz
#pragma config WDTE = OFF
#pragma config PWRTE = ON
#pragma config MCLRE = OFF
#pragma config BOREN = OFF
#pragma config CP = OFF
#pragma config CPD = OFF
#define _XTAL_FREQ 4000000
#define SDA GPIO4
#define SCL GPIO5
#define SDA_ON GPIO4 = 1
#define SDA_OFF GPIO4 = 0
#define SCL_ON GPIO5 = 1
#define SCL_OFF GPIO5 = 0
#define SDA_OUT TRISIO4 = 0
#define SDA_IN TRISIO4 = 1
#define SCL_OUT TRISIO5 = 0
#define SCL_IN TRISIO5 = 1
#define LCD_addr 0x7C //3E+0
#define wait __delay_us(10) //wait 10us
#define wait_time __delay_us(30) //LCD wait time
#define SDA GPIO4
#define SCL GPIO5
#define SDA_ON GPIO4 = 1
#define SDA_OFF GPIO4 = 0
#define SCL_ON GPIO5 = 1
#define SCL_OFF GPIO5 = 0
#define SDA_OUT TRISIO4 = 0
#define SDA_IN TRISIO4 = 1
#define SCL_OUT TRISIO5 = 0
#define SCL_IN TRISIO5 = 1
#define LCD_addr 0x7C //3E+0
#define wait __delay_us(10) //wait 10us
#define wait_time __delay_us(30) //LCD wait time
/* I2C initialize */
void I2C_init(){
SDA_IN;
SCL_IN;
SDA_ON;
SCL_ON;
}
void I2C_init(){
SDA_IN;
SCL_IN;
SDA_ON;
SCL_ON;
}
/* start condition */
void I2C_start(){
SDA_OUT;
SCL_OUT;
SDA_ON;
SCL_ON;
wait;
SDA_OFF;
wait;
SCL_OFF;
}
void I2C_start(){
SDA_OUT;
SCL_OUT;
SDA_ON;
SCL_ON;
wait;
SDA_OFF;
wait;
SCL_OFF;
}
/* stop condition */
void I2C_stop(){
SDA_OFF;
SCL_OFF;
wait;
SCL_ON;
wait;
SDA_ON;
SDA_IN;
SCL_IN;
}
void I2C_stop(){
SDA_OFF;
SCL_OFF;
wait;
SCL_ON;
wait;
SDA_ON;
SDA_IN;
SCL_IN;
}
/* I2C write 1byte */
unsigned char I2C_write(unsigned char byte){
unsigned char ACK = 0;
for(unsigned char i=0;i<8;i++){
SCL_OFF;
wait;
if(byte & 0x80){
SDA_ON;
}else{
SDA_OFF;
}
byte <<=1;
wait;
SCL_ON;
wait;
SCL_OFF;
}
//Get ACK
SDA_IN;
wait;
SCL_ON;
wait;
ACK = SDA;
SCL_OFF;
SDA_OUT;
unsigned char I2C_write(unsigned char byte){
unsigned char ACK = 0;
for(unsigned char i=0;i<8;i++){
SCL_OFF;
wait;
if(byte & 0x80){
SDA_ON;
}else{
SDA_OFF;
}
byte <<=1;
wait;
SCL_ON;
wait;
SCL_OFF;
}
//Get ACK
SDA_IN;
wait;
SCL_ON;
wait;
ACK = SDA;
SCL_OFF;
SDA_OUT;
return ACK;
}
}
/* write command */
void LCD_cmd(unsigned char cmd){
unsigned char ackn;
I2C_start(); //start condition
ackn = I2C_write(LCD_addr); //send slave address
ackn = I2C_write(0x00); //send control byte
ackn = I2C_write(cmd); //send command
I2C_stop(); //stop condition
}
/* write charactor */
void LCD_char(unsigned char dat){
unsigned char ackn;
I2C_start(); //start condition
ackn = I2C_write(LCD_addr); //send slave address
ackn = I2C_write(0x40); //send control byte
ackn = I2C_write(dat); //send data
I2C_stop(); //stop condition
}
void LCD_cmd(unsigned char cmd){
unsigned char ackn;
I2C_start(); //start condition
ackn = I2C_write(LCD_addr); //send slave address
ackn = I2C_write(0x00); //send control byte
ackn = I2C_write(cmd); //send command
I2C_stop(); //stop condition
}
/* write charactor */
void LCD_char(unsigned char dat){
unsigned char ackn;
I2C_start(); //start condition
ackn = I2C_write(LCD_addr); //send slave address
ackn = I2C_write(0x40); //send control byte
ackn = I2C_write(dat); //send data
I2C_stop(); //stop condition
}
/* LCD initialize */
void LCD_init(){
__delay_ms(40); //40ms wait
LCD_cmd(0x38); //8bit,2line
LCD_cmd(0x39); //IS=1 : extention mode set
LCD_cmd(0x14); //Internal OSC Frequency
LCD_cmd(0x70); //Contrast set
LCD_cmd(0x56); //Power/ICON/Contrast Control
LCD_cmd(0x6C); //Follower control
__delay_ms(200);//200ms wait
LCD_cmd(0x38); //IS=0 : extention mode cancel
LCD_cmd(0x0C); //Display ON
LCD_cmd(0x01); //Clear Display
__delay_ms(2); //wait more than 1.08ms
}
void LCD_init(){
__delay_ms(40); //40ms wait
LCD_cmd(0x38); //8bit,2line
LCD_cmd(0x39); //IS=1 : extention mode set
LCD_cmd(0x14); //Internal OSC Frequency
LCD_cmd(0x70); //Contrast set
LCD_cmd(0x56); //Power/ICON/Contrast Control
LCD_cmd(0x6C); //Follower control
__delay_ms(200);//200ms wait
LCD_cmd(0x38); //IS=0 : extention mode cancel
LCD_cmd(0x0C); //Display ON
LCD_cmd(0x01); //Clear Display
__delay_ms(2); //wait more than 1.08ms
}
/* Clear Display */
void LCD_clear(){
LCD_cmd(0x01);
__delay_ms(1);
__delay_us(80);
}
void LCD_clear(){
LCD_cmd(0x01);
__delay_ms(1);
__delay_us(80);
}
/* Return Home */
void LCD_home(){
LCD_cmd(0x02);
__delay_ms(1);
__delay_us(80);
}
void LCD_home(){
LCD_cmd(0x02);
__delay_ms(1);
__delay_us(80);
}
/* Cursor 2line top */
void LCD_2line(){
LCD_cmd(0xC0);
}
void LCD_2line(){
LCD_cmd(0xC0);
}
/* write 1 charactor to LCD */
void putch(unsigned char ch){
LCD_char(ch);
}
void putch(unsigned char ch){
LCD_char(ch);
}
/* main program */
void main() {
CMCON = 0x07; //comparater disable
ANSEL = 0x00; //all port is digital
TRISIO = 0b00110000; //GP4,GP5 input GP0,GP1,GP2,GP3 output
I2C_init(); //I2C initialize
LCD_init(); //LCD initialize
LCD_home();
printf("JH7UBC");
unsigned char count = 0;
void main() {
CMCON = 0x07; //comparater disable
ANSEL = 0x00; //all port is digital
TRISIO = 0b00110000; //GP4,GP5 input GP0,GP1,GP2,GP3 output
I2C_init(); //I2C initialize
LCD_init(); //LCD initialize
LCD_home();
printf("JH7UBC");
unsigned char count = 0;
while(1){
LCD_2line();
printf("%3d",count);
__delay_ms(1000);
count++;
}
}
--------------------------------------
LCD_2line();
printf("%3d",count);
__delay_ms(1000);
count++;
}
}
--------------------------------------
表示結果です。1行目にコールサイン、2行目に数字のカウントアップを表示しました。
文字、数字を表示するのに、printf()構文を使えるようにするために、putch()関数を定義しました。
これで、簡単に文字列、様々なフォーマットで数値を表示できます。
ただ、難点はプログラムサイズが大きくなることです。今回は、プログラムのメモリ占有率は、約72%に達しています。この問題は、メモリ容量の大きいPICを使うことで解決できます。
無料で使用できるMPLBXを使っていますので、文句は言えませんが、有料版なら最適化をして、プログラムサイズが小さくなり、速度も向上するのでしょうね。(やったことがないので分かりませんが・・・)