usrlib-lcd.h
LCDに文字列を表示する関数です.
●この関数は、SC1062というLCD製品に対応しています.
●この関数はfCPU=16MHzで使うことを前提にしています.
遅延時間をfor-next文で作っているところがあります.
●TIM3を占有してしまいます.
●LCDのピンには次のポートを接続していることを前提としています.
ポート
|
LCDコネクタ
|
ポート
|
PA6
|
DB7
|
14
|
13
|
DB6
|
PA5
|
PA3
|
DB5
|
12
|
11
|
DB4
|
PA3
|
---
|
DB3
|
10
|
9
|
DB2
|
---
|
---
|
DB1
|
8
|
7
|
DB0
|
---
|
PG1
|
E
|
6
|
5
|
RW
|
GND
|
PG0
|
RS
|
4
|
3
|
VO
|
PD2 TIM3_CH1
|
GND
|
GND
|
2
|
1
|
VCC
|
5V
|
// LCD initialization routine
void LCD_Init(void); LCDルーチンを初期化する関数.LCDを使う前にコールします.
下記はLCDに書く基本的な関数です.この関数を直接コールする場面はないでしょう.
void LCD_Write_Nibble(u8 RS, char C); 4bitをLCDに書く関数
void LCD_Write_Char(u8 RS, char C); 8bitをLCDに書く関数
引数のRSは次のどちらかです.
#define LCD_REG_FUNC 0 LCDのfunctionレジスタへ書く
#define LCD_REG_CHAR 1 LCDのcharacterレジスタへ書く
下記は文字列をLCDに書く関数です.頻繁に使います.
void LCD_PutString(char *str, u8 line);
引数のlineは次のどちらかです.
#define LCD_DISP_UPPERLINE 0 上の行へ書く
#define LCD_DISP_LOWERLINE 1 下の行へ書く
usrlib-lcd.c
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "stm8s.h"
#include "usrlib-lcd.h"
void LCD_Init(void) LCDを初期化する関数
{
volatile int i; volatileはコンパイラが削除しないようにする指示です.タイマのためのfor-next loopでiを使うため.
GPIO_Init(GPIOG, GPIO_PIN_0, GPIO_MODE_OUT_PP_HIGH_FAST); // LCD RS LCDへ接続する出力ポートの設定
GPIO_Init(GPIOG, GPIO_PIN_1, GPIO_MODE_OUT_PP_HIGH_FAST); // LCD E
GPIO_Init(GPIOA, GPIO_PIN_3, GPIO_MODE_OUT_PP_HIGH_FAST); // LCD DB4
GPIO_Init(GPIOA, GPIO_PIN_4, GPIO_MODE_OUT_PP_HIGH_FAST); // LCD DB5
GPIO_Init(GPIOA, GPIO_PIN_5, GPIO_MODE_OUT_PP_HIGH_FAST); // LCD DB6
GPIO_Init(GPIOA, GPIO_PIN_6, GPIO_MODE_OUT_PP_HIGH_FAST); // LCD DB7
// LCD contrast PWD (TIM3_CH1 [43pin])
TIM3_DeInit();
@TIM3_TimeBaseInit( TIM3_PRESCALER_1, 159 ); // 16MHz/1/160=100kHz
TIM3_OC1Init( ATIM3_OCMODE_PWM1, TIM3_OUTPUTSTATE_ENABLE, B40, TIM3_OCPOLARITY_HIGH );
TIM3_Cmd(ENABLE);
LCDは、コントラストを調節するためのDC電圧を必要とします.それをタイマ3によるPWMで作ります.
TIM3のCH1にPWMが出力されます.TIM3_CH1はPD2です.
@100kHzのPWMを生成させます
APWMモードにします
Bduty比=40/160=25%にします.コントラストを強くするには40を小さな値に変更します.
for(i=0;i<=20000;i++){;} // wait 20mS
for-nextで20mSの遅延を作ります.
volatileでiを宣言した理由はこのためです.非volatileだとコンパイラがこのfor-nextを削除してくれちゃいますので遅延できなくなります.
LCD_Write_Nibble(LCD_REG_FUNC,0b0011); LCDのfunctionレジスタに8bitインターフェースモードを設定
for(i=0;i<=5000;i++){;} 5ms delay
LCD_Write_Nibble(LCD_REG_FUNC,0b0011); LCDのfunctionレジスタに8bitインターフェースモードを設定
for(i=0;i<=20;i++){;} 100us delay
LCD_Write_Nibble(LCD_REG_FUNC,0b0011); LCDのfunctionレジスタに8bitインターフェースモードを設定
LCD_Write_Nibble(LCD_REG_FUNC,0b0010); LCDのfunctionレジスタに4bitインターフェースモードを設定
LCD_Write_Nibble(LCD_REG_FUNC,0b0010); LCDのfunctionレジスタに4bitインターフェースモードを設定
LCD_Write_Nibble(LCD_REG_FUNC,0b1000); LCDのfunctionレジスタに2行、5x7dotモードを設定
LCD_Write_Nibble(LCD_REG_FUNC,0b0000); LCDのfunctionレジスタに表示オフを設定
LCD_Write_Nibble(LCD_REG_FUNC,0b1000); LCDのfunctionレジスタに表示オフを設定
LCD_Write_Nibble(LCD_REG_FUNC,0b0000); LCDのfunctionレジスタに表示クリアを設定
LCD_Write_Nibble(LCD_REG_FUNC,0b0001); LCDのfunctionレジスタに表示クリアを設定
for(i=0;i<=2000;i++){;} 2ms delay
LCD_Write_Nibble(LCD_REG_FUNC,0b0000); LCDのfunctionレジスタにインクリメント、シフトせずを設定
LCD_Write_Nibble(LCD_REG_FUNC,0b1100); LCDのfunctionレジスタにインクリメント、シフトせずを設定
}
// LCD 4bit transfer routine (50uSec wait)
void LCD_Write_Nibble(u8 RS,char C) LCDへ4bit書く関数.解説は省略.
{
volatile int i;
if(RS==0) GPIO_WriteLow ( GPIOG, GPIO_PIN_0 ); // RS
if(RS==1) GPIO_WriteHigh( GPIOG, GPIO_PIN_0 );
if((C&1)==0) GPIO_WriteLow ( GPIOA, GPIO_PIN_3 ); // DB0=data[0]
if((C&1)==1) GPIO_WriteHigh( GPIOA, GPIO_PIN_3 );
if((C&2)==0) GPIO_WriteLow ( GPIOA, GPIO_PIN_4 ); // DB1=data[1]
if((C&2)==2) GPIO_WriteHigh( GPIOA, GPIO_PIN_4 );
if((C&4)==0) GPIO_WriteLow ( GPIOA, GPIO_PIN_5 ); // DB2=data[2]
if((C&4)==4) GPIO_WriteHigh( GPIOA, GPIO_PIN_5 );
if((C&8)==0) GPIO_WriteLow ( GPIOA, GPIO_PIN_6 ); // DB3=data[3]
if((C&8)==8) GPIO_WriteHigh( GPIOA, GPIO_PIN_6 );
GPIO_WriteHigh( GPIOG, GPIO_PIN_1 ); // E
GPIO_WriteLow ( GPIOG, GPIO_PIN_1 );
for(i=0;i<=20;i++){;} // wait 50uS
}
void LCD_Write_Char(u8 RS,char C) LCDへ8bit書く関数.解説は省略.
{
LCD_Write_Nibble(RS,C>>4);
LCD_Write_Nibble(RS,C);
}
void LCD_PutString(char *str, u8 line) LCDへ文字列を書く関数
{
int i,len;
len=strlen(str); 文字列長
if(len>20)len=20; LCDが20文字なので最大でも20文字に制限
for(i=0;i<=len-1;i++) 文字数
{
if(i==0)
{
if(line==LCD_DISP_UPPERLINE)
LCD_Write_Char(LCD_REG_FUNC,0b10000000); // DDRAM-adrs=0
1行目に書きたいならそのように設定
if(line==LCD_DISP_LOWERLINE)
LCD_Write_Char(LCD_REG_FUNC,0b11000000); // DDRAM-adrs=40H
2行目に書きたいならそのように設定
}
LCD_Write_Char(LCD_REG_CHAR,str[i]); LCDへ1文字書く
}
}