2014年5月18日 星期日

TM4C123GXL Launchpad 與 LCD1602

LCD 1602 是容易取得而且價格便宜的 文字型 LCD 模組 , 在電子材料行或是拍賣網站都有 . 控制晶片大部分是日立生產的 HD44780  .  這一次就用它來顯示計數器 . 因為 LCD 1602 module 有 5 V 和 3.3 V 兩種 . 測試了一下這兩個都可以 . 只不過在供給 LCD 1602 module 電源時, 如果 LCD 1602 module 是 5 V 的話 , 要接 Launchpad 上的 VBUS ,  那如果是 3.3 V 的 module , 當然接 Launchpad 上的 3.3 V .

底下是接線圖 : (3.3V LCD 1602 module)

LCD1602 module 共有 16 Pins. 與 TM4C123GXL Lanchpad 的接腳如下 :


其中 LCD1602 的 Pin 3 接一個 3.9k 歐姆的電阻對地(圖上畫的是 3.3k, 那是因為沒找到 3.9k, 所以用 3.3k 代替) . 這地方是調整對比的 , 如果太暗或太亮造成看不清楚顯示的字, 可以接一個 10k 歐姆的可變電阻來調整.  接法如下 :


接下來寫一個 LCD1602 的 Driver , 方便我們使用 . 參考一下它的 Data Sheet . 在 LCD1602.h 中放我們程式函式的原型. 而 LCD1602.c 則是函式的內容 . 當要使用時 , 在我們的主程式中要加入 #include  "LCD1602.h" , 並且要將 LCD1602.c 加入我們的 Project 中.

LCD1602.h :

/*********************************************************************************
**********************************************************************************
**                                  LCD1602.h                                   **
** 1. Support TIVA-C TM4C123GXL Launchpad                                       **
** 2. PIN ASSIGNMENT --> RW-PA5, RS-PA6, E-PA7,  D0~D7 => PB0~PB7         **
** 3. Michael @2014/05/10                                                       **
** 4. Version 1.0                                                               **
**********************************************************************************    
*********************************************************************************/
/* Hardware connection between Launchpad and LCD1602 module    
||     Lauchpad Pin         <==>      LCD1602 Pin      
||         GND              <==>         Pin1
||         Vcc              <==>         Pin2 (3.3V)
||         GND              <==>         Pin3 (connect a 3.9k to GND) 
||         PA6              <==>         Pin4  (RS)
||         PA5              <==>         Pin5  (R/W, To GND is only enable to write)
||         PA7              <==>         Pin6  (E)
||         PB0              <==>         Pin7
||         PB1              <==>         Pin8
||         PB2              <==>         Pin9
||         PB3              <==>         Pin10
||         PB4              <==>         Pin11
||         PB5              <==>         Pin12
||         PB6              <==>         Pin13
||         PB7              <==>         Pin14                    
||         Vcc              <==>         Pin15,  (A, connect a 330R to Vcc)
||         GND              <==>         Pin16,  (K, connect to Ground) */

#define LINE1 0x80 //First Line of LCD1602
#define LINE2 0xC0 //Second Line of LCD1602
//********************************************************************************
//LCD1602 Initialize: 
//********************************************************************************
void LCD1602_Init(void);

//********************************************************************************
//LCD1602 Clear Screen: 
//********************************************************************************
void LCD1602_Clear(void);

//********************************************************************************
//LCD1602 Display String to Screen: 
//********************************************************************************
void LCD1602_DisplayString(unsigned char *str);

//********************************************************************************
//LCD1602 Display Char to Screen: 
//********************************************************************************
void LCD1602_DisplayChar(unsigned char CHAR);

//********************************************************************************
//LCD1602 Display Decimal number to Screen:
//********************************************************************************
void LCD1602_DisplayDec(unsigned int number);

//********************************************************************************
//LCD1602 Set Cursor Position on the Screen: 
//Line : LINE1 or LINE2
//Digit : from 0 ~ 15
//********************************************************************************
void LCD1602_DisplayPosition(unsigned char Line,unsigned int digit);


LCD1602.c :

/*********************************************************************************
**********************************************************************************
**                                  LCD1602.c                                   **
** 1. Support TIVA-C TM4C123GXL Launchpad                                       **
** 2. PIN ASSIGNMENT --> RW-PA5, RS-PA6, E-PA7,  D0~D7 => PB0~PB7         **
** 3. Michael @2014/05/10                                                       **
** 4. Version 1.0                                                               **
**********************************************************************************    
*********************************************************************************/
/* Hardware connection between Launchpad and LCD1602 module    
||     Lauchpad Pin         <==>      LCD1602 Pin      
||         GND              <==>         Pin1
||         Vcc              <==>         Pin2 (3.3V)
||         GND              <==>         Pin3 (connect a 3.9k to GND) 
||         PA6              <==>         Pin4  (RS)
||         PA5              <==>         Pin5  (R/W, To GND is only enable to write)
||         PA7              <==>         Pin6  (E)
||         PB0              <==>         Pin7
||         PB1              <==>         Pin8
||         PB2              <==>         Pin9
||         PB3              <==>         Pin10
||         PB4              <==>         Pin11
||         PB5              <==>         Pin12
||         PB6              <==>         Pin13
||         PB7              <==>         Pin14                    
||         Vcc              <==>         Pin15,  (A, connect a 330R to Vcc)
||         GND              <==>         Pin16,  (K, connect to Ground) */

#include <stdint.h>
#include <stdio.h>
#include "inc/tm4c123gh6pm.h"
#include "LCD1602.h"
#include "SYSTICK.h"

#define RW 0x20  //PA5
#define RS 0x40  //PA6 
#define E  0x80  //PA7

//********************************************************************************
// LCD1602 Initial GPIO PORTB and PORTA- PA5,PA6,PA7 : GPIO_PortAB_Init()
//********************************************************************************
void GPIO_PortAB_Init(void){
    volatile unsigned long delay;
    //Initial PA7/PA6/PA5
    SYSCTL_RCGC2_R |= 0x00000001;     
    delay = SYSCTL_RCGC2_R;   
    GPIO_PORTA_AMSEL_R &= ~0xE0;      
    GPIO_PORTA_PCTL_R &= ~0xFFF00000;                    
    GPIO_PORTA_DIR_R |= 0xE0;         
    GPIO_PORTA_AFSEL_R &= ~0xE0;           
    GPIO_PORTA_DEN_R |= 0xE0;
    GPIO_PORTA_DR8R_R |= 0xE0;

    //Initial PB7 ~ 0
    SYSCTL_RCGC2_R |= 0x00000002;     
    delay = SYSCTL_RCGC2_R;   
    GPIO_PORTB_AMSEL_R &= ~0xFF;      
    GPIO_PORTB_PCTL_R &= ~0xFFFFFFFF;                    
    GPIO_PORTB_DIR_R |= 0xFF;         
    GPIO_PORTB_AFSEL_R &= ~0xFF;           
    GPIO_PORTB_DEN_R |= 0xFF;
    GPIO_PORTB_DR8R_R |= 0xFF;
}

//********************************************************************************
//LCD1602 Write Commend to LCD module
//********************************************************************************
void Write_Command(unsigned char LCD_Comment){
    GPIO_PORTA_DATA_R &= ~(RS+RW+E);     //RS=0,RW=0,E=0
    GPIO_PORTB_DATA_R = LCD_Comment;         //Write Command    
    GPIO_PORTA_DATA_R |= E;                  //RS=0,RW=0,E=1
    GPIO_PORTA_DATA_R &= ~(RS+RW);
    SysTick_Delay(19);                       //Enable width 230 ns
    GPIO_PORTA_DATA_R &= ~(RS+RW+E);     //RS=0,RW=0,E=0
    SysTick_Delay1ms(1);                     //Delay 1 ms
}
//********************************************************************************
//LCD1602 Write DATA to LCD module
//********************************************************************************
void Write_Data(unsigned char LCD_Data){
    GPIO_PORTB_DATA_R = LCD_Data;            //Write Data
    GPIO_PORTA_DATA_R |= RS+E;               //RS=1,RW=0,E=1
    GPIO_PORTA_DATA_R &= ~RW;
    SysTick_Delay(19);                       //Enable width 230 ns
    GPIO_PORTA_DATA_R &= ~(RS+RW+E);     //RS=0,RW=0,E=0
    SysTick_Delay1ms(1);                     //Delay 1 ms
}     
//********************************************************************************
//LCD1602 Initialize: 
//********************************************************************************
void LCD1602_Init(){        
    GPIO_PortAB_Init();
    SysTick_Delay1ms(15);                    //Delay 15ms   
    Write_Command(0x38);
    SysTick_Delay1ms(5);                     //Delay 5ms  
    Write_Command(0x38);
    SysTick_Delay1us(150);                   //Delay 150us      
        
    Write_Command(0x0C);            
    Write_Command(0x01);            
    Write_Command(0x06);
            
    SysTick_Delay1ms(50);                    //Delay 50ms    
}      
//********************************************************************************
//LCD1602 Clear Screen:
//********************************************************************************
void LCD1602_Clear(){
    Write_Command(0x01);    
}

//********************************************************************************
//LCD1602 Display String to Screen: 
//********************************************************************************
void LCD1602_DisplayString(unsigned char *str){      
    while(*str != 0){
        Write_Data(*str++);                  
    }    
}

//********************************************************************************
//LCD1602 Display Char to Screen: 
//********************************************************************************
void LCD1602_DisplayChar(unsigned char CHAR){      
    Write_Data(CHAR);      
}

//********************************************************************************
//LCD1602 Display Decimal number to Screen: 
//********************************************************************************
void LCD1602_DisplayDec(unsigned int number){   
    if(number >=10){
        LCD1602_DisplayDec(number/10);
        number = number%10;
    }
    LCD1602_DisplayChar(number+'0');   
}
//********************************************************************************
//LCD1602 Set Cursor Position on the Screen: 
//********************************************************************************
void LCD1602_DisplayPosition(unsigned char Line,unsigned int digit){   
    Write_Command(Line + digit);
}
//********************************************************************************
//LCD1602 support printf() function
//********************************************************************************
int fputc(int ch, FILE *f){
    if((ch == 10) || (ch == 13) || (ch == 27)){
        LCD1602_DisplayChar(13);
        LCD1602_DisplayChar(10);
        return 1;
    }
    LCD1602_DisplayChar(ch);
    return 1;
}


接下來也整理一下之前寫過的 PLL 和 SYSTICK 部分 , 把它們改為模組化 , 如 PLL_80MHZ.c 和 PLL_80MHZ.h 以及 SYSTICK.c 和 SYSTICK.h , 那麼以後要用到就可直接加入 Project 中, 不用再重寫了 . 如下 :

PLL_80MHZ.h :

/*********************************************************************************
**********************************************************************************
**                                  PLL_80MHZ.h                                 **
** 1. Board : TIVA-C TM4C123GXL Launchpad                                       **
** 2. Use PLL to set System Clock to 80MHZ                                      **
** 3. Michael @2014/05/10                                                       **
** 4. Version 1.0                                                               **
**********************************************************************************    
*********************************************************************************/

//********************************************************************************
//                  USE PLL to set system clock to 80MHZ
//********************************************************************************
//Initial PLL 80MHZ
void PLL_Init80MHZ(void);



PLL_80MHZ.c :

/*********************************************************************************
**********************************************************************************
**                                  PLL_80MHZ.c                                 **
** 1. Board : TIVA-C TM4C123GXL Launchpad                                       **
** 2. Use PLL to set System Clock to 80MHZ                                      **
** 3. Michael @2014/05/10                                                       **
** 4. Version 1.0                                                               **
**********************************************************************************    
*********************************************************************************/

#include <stdint.h>
#include "inc/tm4c123gh6pm.h"
#include "PLL_80MHZ.h"

//********************************************************************************
//                  USE PLL to set system clock to 80MHZ
//********************************************************************************
//Initial PLL 80MHZ
void PLL_Init80MHZ(void)
{    
    SYSCTL_RCC2_R |=  0x80000000;   
    SYSCTL_RCC2_R |=  0x00000800;  
    SYSCTL_RCC_R = (SYSCTL_RCC_R &~0x000007C0)   
                 + 0x00000540;   
    SYSCTL_RCC2_R &= ~0x00000070;  
    SYSCTL_RCC2_R &= ~0x00002000;  
    SYSCTL_RCC2_R |= 0x40000000;   
    SYSCTL_RCC2_R = (SYSCTL_RCC2_R&~ 0x1FC00000)  
                  + (4<<22);  
    while((SYSCTL_RIS_R&0x00000040)==0){};  
    SYSCTL_RCC2_R &= ~0x00000800;
}


SYSTICK.h

/*********************************************************************************
**********************************************************************************
**                                  SYSTICK.h                                   **
** 1. Support TIVA-C TM4C123GXL Launchpad                                       **
** 2. Assume System Clock is 80MHZ                                              **
** 3. Michael @2014/05/10                                                       **
** 4. Version 1.0                                                               **
**********************************************************************************    
*********************************************************************************/

//********************************************************************************
//Systick Initialize: 
//********************************************************************************
void SysTick_Init(void);

//********************************************************************************
//Systick 12.5 ns Delay: 
//********************************************************************************
void SysTick_Delay(unsigned long delay);

//********************************************************************************
//Systick 1 us Delay: 
//********************************************************************************
void SysTick_Delay1us(unsigned long delay);

//********************************************************************************
//Systick 1 ms Delay: 
//********************************************************************************
void SysTick_Delay1ms(unsigned long delay);


SYSTICK.c

/*********************************************************************************
**********************************************************************************
**                                  SYSTICK.c                                   **
** 1. Support TIVA-C TM4C123GXL Launchpad                                       **
** 2. Assume System Clock is 80MHZ                                              **
** 3. Michael @2014/05/10                                                       **
** 4. Version 1.0                                                               **
**********************************************************************************    
*********************************************************************************/

#include <stdint.h>
#include "inc/tm4c123gh6pm.h"
#include "SYSTICK.h"

//********************************************************************************
//                  SysTick Timer Assume System clock is 80MHZ
//********************************************************************************

//********************************************************************************
//Systick Initialize:
//********************************************************************************
//Initial Systick Timer
void SysTick_Init(void){
    NVIC_ST_CTRL_R = 0;               
    NVIC_ST_CTRL_R = 0x00000005;      
}

//********************************************************************************
//Systick 12.5 ns Delay: 
//********************************************************************************
// The delay parameter is 12.5ns in 80 MHz core clock.
void SysTick_Delay(unsigned long delay){
    NVIC_ST_RELOAD_R = delay-1;  
    NVIC_ST_CURRENT_R = 0;       
    while((NVIC_ST_CTRL_R&0x00010000)==0){ 
    }
}

//********************************************************************************
//Systick 1 us Delay: 
//********************************************************************************
// 80*12.5ns => 1 us
void SysTick_Delay1us(unsigned long delay){
    unsigned long i;
    for(i=0; i<delay; i++)    {
       SysTick_Delay(80);                 // wait 1us
    }
}

//********************************************************************************
//Systick 1 ms Delay: 
//********************************************************************************
// 80000*12.5ns => 1 ms
void SysTick_Delay1ms(unsigned long delay){
    unsigned long i;
    for(i=0; i<delay; i++)    {
       SysTick_Delay(80000);              // wait 1ms
    }
}



現在我們來新建一個 LCD1602 的 Project . 如何建立請參考 " 如何使用 Keil 建立一個新 project for TM4C123G Launchpad " 這篇文章 .

這裡有一個地方要注意 , 在 " Option of Target " 的 Target 頁面中 , 要勾選 Use MicroLib . 如下圖所示 . 因為我們要使用 printf 功能 .


記得要將 LCD1602.c , PLL_80MHZ.c  和 SYSTICK.c 加入 Project 中 , 如下 :

底下是 main.c :


/*********************************************************************************
**********************************************************************************
**                             LCD 1602 Module Experiment                       **
**  1. Write a driver of LCD1602 for TM4C123GXL Launchpad                       **
**  2. Modularize for Systick, PLL_80MHZ                                        **
**  3. LCD1602 with Launchpad detail connection please refer to LCD1602.h file  **
**  4. Initial LCD1602 module and display a string and a counter which count    **
**     per second.                                                              **
**  5. Michael @ 2014/05/10                                                     **
**********************************************************************************    
*********************************************************************************/

#include <stdint.h>
#include <stdio.h>
#include "inc/tm4c123gh6pm.h"
#include "LCD1602.h"
#include "SYSTICK.h"
#include "PLL_80MHZ.h"

void PLL_Init(void);

unsigned char msg1[] = {0x54,0x4D,0x34,0x43,0x32,0x33,0x47,0x58,0x4C}; //ASCII code for "TM4C123GXL"
unsigned char *msg[1] = {msg1};

int main(void){
    unsigned int counter=0;
    PLL_Init80MHZ();
    SysTick_Init();
    LCD1602_Init();
    LCD1602_DisplayPosition(LINE1,3);
    LCD1602_DisplayString(msg[0]);
    
    while(1)
    {
        LCD1602_DisplayPosition(LINE2,7);
        LCD1602_DisplayDec(counter);        
        counter ++;
        SysTick_Delay1ms(1000);
    }
}
// Use printf function 
// To use this, please comment out above int main() and re-name below int main1() to int main()
int main1(void){
    unsigned int counter=0;
    PLL_Init80MHZ();
    SysTick_Init();
    LCD1602_Init();
    LCD1602_DisplayPosition(LINE1,3);    
    printf("TM4C123GXL");
    while(1)
    {
        LCD1602_DisplayPosition(LINE2,7);        
        printf("%d",counter);
        counter ++;
        SysTick_Delay1ms(1000);
    }
}


這裡說明一下 , 這裡有兩個 main function . int main() 是用一般的方式顯示字串和計數 . int main1()則是採用 printf() function . 這會方便許多 . 不過注意要加入 #include . 要試第二個也就是 int main1() 時 , 就是把第一個也就是 int main() 全部註解掉 . 然後把 int main1() 改為 int main() 就可以了 . 這一篇就寫到這裡了 . 

參考文獻 :
Embedded Systems: Introduction to ARM® Cortex-M Microcontrollers - Jonathan Valvano
Getting Started with the Tiva™ TM4C123G LaunchPad Workshop
TM4C123GH6PM DATA SHEET
Embedded Systems Shape The World

沒有留言:

張貼留言