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文字書く
    }
}

inserted by FC2 system