×
[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
またしても、STM32F030F4P6でLCD表示を行う記事です。
今回はNokia5110というグラフィック液晶ディスプレーです。
1602よりも若干高めで、そもそも、供給源が解体された携帯電話からの回収部品であるために、市場からは1602よりも早く駆逐されてしまうと思いますが、決められたキャラクター文字しか表示できない1602よりも、表現力は上で、使い勝手は圧倒的に勝るはずです。
とはいえ、まだ「表示できた」というだけのレベルで、文字や記号を表示するには至っていません。
今回は、「ちゃんと制御できた」ということを検証するためのデモプログラムという事になりますが、ここまでくればあとはどうにでもなるんじゃないかな? と思います。
とにかく、「ここまで来る道のり」が厳しかったです。
/*
**********************************************************************
**
** Main.c
** SPI-5110
** EmBitz
**
** A1-Input (現在は未使用)
** A5-Output RS (Reset)
** A6-Output CE (Master In Slave Out:Low=GND)
** A7-Output DC (Data/Command:Data=High_Command=Low)
** A2-Output DIN (Serial Input:送信Data)
** A3-Output CLK (Serial Clock)
** A4-Output LED (DL)
**
** 空のprojectを作成し、設定をhexファイルが取得できるように変更して、
** main.cにこの文章をcopy&pasteして、コンパイルすれば完成です
**
**
**********************************************************************/
/*
Last committed: $Revision: 27X$
Last changed by: $Author: Masaomi.Takahashi.$
Last changed date: $Date: 2019-09-01
ID: $Id: 0025
**********************************************************************/
#include "stm32f0xx.h"
int tt,tx; //画面更新のタイミング。Belay間隔。tx=実効値。tt=初期値。
int k; //描写する幅を少しずつ減らしてゆく為の変数。
int main(void)
{
RCC ->AHBENR |= (1<<17); // GPIO-Aの初期化(最初は0クロックで無可動状態)
GPIOA -> IDR |= (1<<2); // ピン A - 1 を入力モードに
GPIOA -> PUPDR |= (1<<2); // ピン A - 1 を プルアップ指定
GPIOA -> MODER |= (1<<4); // ピン A - 2 を出力モードに lcd-MOSI 送信データ。
GPIOA -> PUPDR |= (1<<4); // ピン A - 2 を プルアップ指定
GPIOA -> MODER |= (1<<6); // ピン A - 3 を出力モードに lcd-CLK クロック
GPIOA -> PUPDR |= (1<<6); // ピン A - 3 を プルアップ指定
GPIOA -> MODER |= (1<<8); // ピン A - 4 を出力モードに lcd-LED 赤=Low/青=Highで点灯
GPIOA -> PUPDR |= (1<<8); // ピン A - 4 を プルアップ指定
GPIOA -> MODER |= (1<<10); // ピン A - 5 を出力モードに lcd-RS リセット
GPIOA -> PUPDR |= (1<<10); // ピン A - 5 を プルアップ指定
GPIOA -> MODER |= (1<<12); // ピン A - 6 を出力モードに lcd-CE 入力データ (Low=GND)
GPIOA -> PUPDR |= (1<<12); // ピン A - 6 を プルアップ指定
GPIOA -> MODER |= (1<<14); // ピン A - 7 を出力モードに lcd-DC データ/コマンド
GPIOA -> PUPDR |= (1<<14); // ピン A - 7 を プルアップ指定
GPIOA ->ODR &= ~(1<<2); //GPIOA-Pin2をOffにする
GPIOA ->ODR &= ~(1<<3); //GPIOA-Pin3をOffにする
GPIOA ->ODR &= ~(1<<4); //GPIOA-Pin4をOffにする LEDなので、Onでも可
GPIOA ->ODR &= ~(1<<5); //GPIOA-Pin5をOffにする
GPIOA ->ODR &= ~(1<<6); //GPIOA-Pin6をOffにする
GPIOA ->ODR &= ~(1<<7); //GPIOA-Pin7をOffにする
delay_us(1);
lcd_init();
while(1){
tt=850;
while(tt>=0){
if (tt>=550)
tx=tt-550;
else
tx=0;
lcd_position(0,0);
int i=84*6;
while(i>0){
lcd_put_ch(0xFF);
i--;
}
delay_ms(tx);
lcd_position(0,0);
i=84*6;
while(i>0){
lcd_put_ch(0x7F);
i--;
}
delay_ms(tx);
lcd_position(0,0);
i=84*6;
while(i>0){
lcd_put_ch(0x3F);
i--;
}
delay_ms(tx);
lcd_position(0,0);
i=84*6;
while(i>0){
lcd_put_ch(0x1F);
i--;
}
delay_ms(tx);
lcd_position(0,0);
i=84*6;
while(i>0){
lcd_put_ch(0x0F);
i--;
}
delay_ms(tx);
lcd_position(0,0);
i=84*6;
while(i>0){
lcd_put_ch(0x07);
i--;
}
delay_ms(tx);
lcd_position(0,0);
i=84*6;
while(i>0){
lcd_put_ch(0x03);
i--;
}
delay_ms(tx);
lcd_position(0,0);
i=84*6;
while(i>0){
lcd_put_ch(0x01);
i--;
}
delay_ms(tx);
lcd_position(0,0);
i=84*6;
while(i>0){
lcd_put_ch(0x00);
i--;
}
delay_ms(tx);
lcd_position(0,0);
i=84*6;
while(i>0){
lcd_put_ch(0xFF);
i--;
}
delay_ms(tx);
k=7;
while(k>0){
lcd_position(0,0);
i=84*6;
int j=0;
while(i>0){
j++;
if (j>=k){
lcd_put_ch(0x00);
// j=0;
}
else{
lcd_put_ch(0xFF);
}
if (j>=7){
j=0;
}
i--;
}
delay_ms(tx);
k--;
}
tt=tt-25;
} } }
//---------- 文字列出力 ----------
// *str:文字列の先頭ポインタ
void lcd_put_str(char *str)
{
while(*str != 0){
lcd_put_ch( *str );
str++;
}
}
//---------- LCD初期化 ----------
void lcd_init()
{
GPIOA ->ODR &= ~(1<<5); //GPIOA-Pin5(RS)をOffにする
GPIOA ->ODR |= (1<<5); //GPIOA-Pin5(RS)をOnにする
delay_ms(2);
GPIOA ->ODR &= ~(1<<6); //GPIOA-Pin6(CE)をOffにする
lcd_put_cmd(0x21); //Extended Commands.
lcd_put_cmd(0xAF); //Contrast Vop=6.4V
lcd_put_cmd(0x04); //Set Temp coefficent.
lcd_put_cmd(0x13); //LCD bias mode 1:48.
lcd_put_cmd(0x20); //Standard Commands.
lcd_put_cmd(0x0C); //Normal mode
lcd_clear(); //Screen Clear.
}
//---------- 表示位置設定 ----------
// xx:x座標 yy:y座標
void lcd_position(int xx, int yy)
{
lcd_put_cmd(0x80 | xx | (0x40 * yy));
}
//---------- データ4bit出力 ----------
void lcd_put_4bit(char code)
{
GPIOA ->ODR &= ~(1<<3); //GPIOA-Pin3をOffにする
if(code & 0x80)
GPIOA ->ODR |= (1<<2); //GPIOA-Pin2をOnにする
else
GPIOA ->ODR &= ~(1<<2); //GPIOA-Pin2をOffにする
GPIOA ->ODR |= (1<<3); //GPIOA-Pin3をOnにする
GPIOA ->ODR &= ~(1<<3); //GPIOA-Pin3をOffにする
if(code & 0x40)
GPIOA ->ODR |= (1<<2); //GPIOA-Pin2をOnにする
else
GPIOA ->ODR &= ~(1<<2); //GPIOA-Pin2をOffにする
GPIOA ->ODR |= (1<<3); //GPIOA-Pin3をOnにする
GPIOA ->ODR &= ~(1<<3); //GPIOA-Pin3をOffにする
if(code & 0x20)
GPIOA ->ODR |= (1<<2); //GPIOA-Pin2をOnにする
else
GPIOA ->ODR &= ~(1<<2); //GPIOA-Pin2をOffにする
GPIOA ->ODR |= (1<<3); //GPIOA-Pin3をOnにする
GPIOA ->ODR &= ~(1<<3); //GPIOA-Pin3をOffにする
if(code & 0x10)
GPIOA ->ODR |= (1<<2); //GPIOA-Pin2をOnにする
else
GPIOA ->ODR &= ~(1<<2); //GPIOA-Pin2をOffにする
GPIOA ->ODR |= (1<<3); //GPIOA-Pin3をOnにする
}
//---------- 1文字出力 ----------
// ch:出力するデータ
void lcd_put_ch(char ch)
{
GPIOA ->ODR &= ~(1<<6); //GPIOA-Pin6(CE)をOffにする
GPIOA ->ODR |= (1<<7); //GPIOA-Pin7(DC)をOnにする
lcd_put_4bit(ch); //上位4bit出力
lcd_put_4bit(ch<<4); //下位4bit出力
GPIOA ->ODR |= (1<<6); //GPIOA-Pin6(CE)をOnにする
}
//---------- コマンド送信 ----------
void lcd_put_cmd(char cmd)
{
GPIOA ->ODR &= ~(1<<6); //GPIOA-Pin6(CE)をOffにする
GPIOA ->ODR &= ~(1<<7); //GPIOA-Pin7(DC)をOffにする
lcd_put_4bit(cmd); //上位4bit出力
lcd_put_4bit(cmd<<4);//下位4bit出力
GPIOA ->ODR |= (1<<6); //GPIOA-Pin6(CE)をOnにする
}
//---------- 塗りつぶし(消去) ----------
void lcd_clear()
{
lcd_position(0,0);
int i=84*6;
while(i>0){
lcd_put_ch(0x00);
i--;
} }
void delay_ms(uint32_t i)
{
i=i*100;
while(i>0){
asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");
asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");
asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");
asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");
i--;
} }
void delay_us(uint32_t i)
{
while(i>0){
asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");
i--;
} }
以上。
恥ずかしくて顔が真っ赤になるような稚拙なプログラムかもしれませんが、所詮は専門的な教育を受けていない素人が、独学で好き勝手やっていることですので、ご理解ください。
(とりあえず、「無駄」とか「美しさ」とかは横に置いておいて、「動けばいい」、というスタンスです)
現在、回路はこんな感じでまとまっています。
消費電力は液晶付きでも10mA未満(簡易計測出来る限界未満)なので、この状況下では不満はないです。
配線はこんな感じ。
基板に落としこむ際に、Youtubeにアップロードした時とPinが随分変更されたのですが、「どうでもいい」話ですね。
この回路だと、USB端子を差しこめば動いてくれるので、ブレッドボードに沢山配線をぶっ刺していた頃と比べて、劇的に検証が楽になっています。
最後に。
この液晶(5110)に対して、STM32は一方的にデータを送信するだけの関係なので、LCDを回路から取り外しても、プログラムの挙動は変わりません。
ですので、ピンに余裕があるのでしたら、LCDはあくまでもシステムを管理する際の補助として使用し、普段はLDCを外して使用する、なんてことが可能です。
プログラムが正常に作動しているかどうかをチェックするだけなら、LCDの代わりにLEDを刺しておいても、ある程度把握できるはずです。
PR
コメント