Sunday 9 July 2017

STM32 L1 Discovery - LCD

20170711.2


This post shall be limited to the LCD on the STM32 L1 Discovery. (STM32L152RC Discovery).
The necessary set up, software etc are similar to the post on STM32F103C8T6.


====================

For operating the LCD on the STM32 L1 Discovery:

1. The LSI is switched on for the operation of the LCD.

2. 28 pins on ports A, B and C are configured as alternate (LCD) functions.

3. The required 96 segments on the LCD have to be mapped on the RAM’s as the microcontroller’s pins do not match the LCD’s pins.

4. The familiar codes for the 7-segment display have been modified and used.



====================

For a start, a previous program has been edited to display a digit on the right-most location of the LCD. Other parts of the program have been removed.

//  T75.c  STM32 L1 Discovery  LCD on Board

#include "stm32l1xx.h"
int C8[]={0x3F,0x06,0xDB,0xCF,0xE6,0xED,0xFD,0x07,0xFF,0xEF,0x06,0xDB} ;
void LCD96conf(void);
void map8to8(int q);
void LCD96map(void);
unsigned long RAM24[4];

int main(){
    int i,j,N ;
  
//  Enable LSI for RTC/LCD                                                                                     
        RCC->APB1ENR  |=     RCC_APB1ENR_PWREN ;
    PWR->CR       |=     PWR_CR_DBP ;
    RCC->CSR      |=     RCC_CSR_LSION ;
    while( (RCC->CSR&RCC_CSR_LSIRDY)==0 );   // Wait till LSE Ready  
    RCC->CSR      &=     ~RCC_CSR_RTCSEL ;   // Mask
    RCC->CSR      |=     RCC_CSR_RTCSEL_LSI ;   
    
    LCD96conf();

// Testing LCD
       RAM24[0] = 0 ;
       RAM24[1] = 0 ;
       RAM24[2] = 0 ;
       RAM24[3] = 0 ;
       map8to8(0xF6);       // This is 'H'
       LCD96map();
       LCD->SR       |=     LCD_SR_UDR ;
       while( (LCD->SR&LCD_SR_UDD)==0 );

       N = 0 ;

       while(1){
         RAM24[0] = 0 ;
         RAM24[1] = 0 ;
         map8to8(C8[N]);    //
         LCD96map();
         LCD->SR       |=     LCD_SR_UDR ;
         while( (LCD->SR&LCD_SR_UDD)==0 );
                 for(i=0;i<=200;i++){ for(j=0;j<=1000;j++);}
                 N++;
         if(N>=10) N = 0 ;
       }
    
}

void map8to8(int q){              // Rightmost digit
       if((q&0x01)==0x01) RAM24[1] |= 0x01<<12 ;
       if((q&0x02)==0x02) RAM24[0] |= 0x01<<12 ;
       if((q&0x04)==0x04) RAM24[1] |= 0x01<<11 ;
       if((q&0x08)==0x08) RAM24[1] |= 0x01<<10 ;
       if((q&0x10)==0x10) RAM24[0] |= 0x01<<10 ;
       if((q&0x20)==0x20) RAM24[1] |= 0x01<<13 ;
       if((q&0x40)==0x40) RAM24[0] |= 0x01<<13 ;
       if((q&0x80)==0x80) RAM24[0] |= 0x01<<11 ;
}   
    
    
void LCD96map(void){
       int b ;                 
                
           //  b = 0,1,2, 3,4,5, 6, 7, 8, 9,10,11, 12,13,14,15,16,17, 18,19,20,21,22,23
       char MAP[]={0,1,2, 7,8,9,10,11,12,13,14,15, 17,16,18,19,20,21, 24,25,26,27,28,29};
             // Bits     3,4,5,6,               22,23,            30,31 not used
              LCD->RAM[0*2]  = 0 ;
              LCD->RAM[1*2]  = 0 ;
              LCD->RAM[2*2]  = 0 ;
              LCD->RAM[3*2]  = 0 ;
              for(b=0;b<=23;b++){
                     LCD->RAM[0*2] |=  (RAM24[0]&(1<<b))<<(MAP[b]-b);
                     LCD->RAM[1*2] |=  (RAM24[1]&(1<<b))<<(MAP[b]-b);
                     LCD->RAM[2*2] |=  (RAM24[2]&(1<<b))<<(MAP[b]-b);
                     LCD->RAM[3*2] |=  (RAM24[3]&(1<<b))<<(MAP[b]-b);
              }
}

void PAaft(char PIN, char FUNC){         // Port A alternate function
  GPIOA->MODER       &=  ~(0x03<<(2*PIN)) ;     // Clear Mode mask
  GPIOA->MODER       |=    0x02<<(2*PIN)  ;     // 0=i; 1=O; 2=AltFun; 3=Analog
  if(PIN<=7){
    GPIOA->AFR[0]    &=  ~(0x0F<<(4*PIN)) ;            // Clear AFR mask
    GPIOA->AFR[0]    |=    FUNC<<(4*PIN) ;             // Alt Func
      } else{
    GPIOA->AFR[1]    &=  ~(0x0F<<(4*(PIN-8))); // Clear AFR mask
    GPIOA->AFR[1]    |=    FUNC<<(4*(PIN-8)) ; // Alt Func
  }
}                               

void PBaft(char PIN, char FUNC){         // Port B alternate function
  GPIOB->MODER       &=  ~(0x03<<(2*PIN)) ;     // Clear Mode mask
  GPIOB->MODER       |=    0x02<<(2*PIN)  ;     // 0=i; 1=O; 2=AltFun; 3=Analog
  if(PIN<=7){
    GPIOB->AFR[0]    &=  ~(0x0F<<(4*PIN)) ;            // Clear AFR mask
    GPIOB->AFR[0]    |=    FUNC<<(4*PIN) ;             // Alt Func
      } else{
    GPIOB->AFR[1]    &=  ~(0x0F<<(4*(PIN-8))); // Clear AFR mask
    GPIOB->AFR[1]    |=    FUNC<<(4*(PIN-8)) ; // Alt Func
  }
}

void PCaft(char PIN, char FUNC){         // Port C alternate function
       GPIOC->MODER         &=  ~(0x03<<(2*PIN)) ;     // Clear Mode mask
       GPIOC->MODER         |=    0x02<<(2*PIN) ;      // 0=i; 1=O; 2=AltFun; 3=Analog
       if(PIN<=7){
              GPIOC->AFR[0] &=  ~(0x0F<<(4*PIN)) ;            // Clear AFR mask
              GPIOC->AFR[0]        |=    FUNC<<(4*PIN) ;             // Alt Func
              } else{
              GPIOC->AFR[1]        &=  ~(0x0F<<(4*(PIN-8))); // Clear AFR mask
              GPIOC->AFR[1]        |=    FUNC<<(4*(PIN-8)) ; // Alt Func
              }
}

void LCD96conf(void){
       char i ;
       char Apins[]={1,2,3,8,9,10,15};          // 7 pins
       char Bpins[]={3,4,5,8,9,10,11,12,13,14,15};     // 11 pins
       char Cpins[]={0,1,2,3,6,7,8,9,10,11};           // 10 pins

       //  LCD on Board  Configuration
       RCC->AHBENR  |=  RCC_AHBENR_GPIOAEN ;
       RCC->AHBENR  |=  RCC_AHBENR_GPIOBEN ;              
       RCC->AHBENR  |=  RCC_AHBENR_GPIOCEN ;              
       for(i=0;i<=6;i++) { PAaft(Apins[i],11);  }
       for(i=0;i<=10;i++){ PBaft(Bpins[i],11);  }
       for(i=0;i<=9;i++) { PCaft(Cpins[i],11);  }

       RCC->APB1ENR  |=  RCC_APB1ENR_LCDEN ; 
       LCD->CR        =      LCD_CR_MUX_SEG | 0x0C | 0x40 ;    // Duty=1/4 Bias=1/3  64-pin !
       LCD->FCR      =  0 ;                    // Reset condition
       LCD->FCR      |=     (4<<22) ;     // PS = 4  (Bits 22,23,24,25)
       LCD->FCR      |=     (1<<18) ;     // DIV = 1  (Bits 18,19,20,21)
       LCD->FCR      |=     (7<<10) ;     // CC = 7  (Bits 10,11,12)
       LCD->FCR      |=     (7<<4) ;      // PON = 7  (Bits 4,5,6)
       LCD->CR       |=     LCD_CR_LCDEN ;
       while( (LCD->SR&LCD_SR_RDY)==0 ); // Wait till ready
}




====================

It is then quite straight forward to display the digits on the other locations.

The right-most digit is at location 0, while the left-most digit is at location 5.

//  T76.c  STM32 L1 Discovery  LCD on Board

#include "stm32l1xx.h"
int C8[]={0x3F,0x06,0xDB,0xCF,0xE6,0xED,0xFD,0x07,0xFF,0xEF,0x06,0xDB} ;
void LCD96conf(void);
void map8to8(int q, int L);
void LCD96map(void);
unsigned long RAM24[4];

int main(){
    int i,j,N,L ;
   
//  Enable LSI for RTC/LCD                                                                                      
        RCC->APB1ENR  |=     RCC_APB1ENR_PWREN ;
    PWR->CR       |=     PWR_CR_DBP ;
    RCC->CSR      |=     RCC_CSR_LSION ;
    while( (RCC->CSR&RCC_CSR_LSIRDY)==0 );   // Wait till LSE Ready   
    RCC->CSR      &=     ~RCC_CSR_RTCSEL ;   // Mask
    RCC->CSR      |=     RCC_CSR_RTCSEL_LSI ;    
     
    LCD96conf();

// Testing LCD
       RAM24[0] = 0 ;
       RAM24[1] = 0 ;
       RAM24[2] = 0 ;
       RAM24[3] = 0 ;
       map8to8(0xF6,0);            // This is 'H'
       LCD96map();
       LCD->SR       |=     LCD_SR_UDR ;
       while( (LCD->SR&LCD_SR_UDD)==0 );

             L = 5 ;   
       N = 0 ;

       while(1){
                    RAM24[0] = 0 ;
                    RAM24[1] = 0 ;
                    if(N==0){
                        L++;
                        if(L==6) L = 0 ;
                    }
                    map8to8(C8[N],L);    //
         LCD96map();
         LCD->SR       |=     LCD_SR_UDR ;
         while( (LCD->SR&LCD_SR_UDD)==0 );
                 for(i=0;i<=200;i++){ for(j=0;j<=1000;j++);}
                 N++;
         if(N>=10) N = 0 ;
       }
     
}

void map8to8(int q, int L){            // L=0 : Rightmost digit
    if((q&0x01)==0x01) RAM24[1] |= 0x01<<(12+2*L) ;        // A +
    if((q&0x02)==0x02) RAM24[0] |= 0x01<<(12+2*L) ;        // B +
    if((q&0x04)==0x04) RAM24[1] |= 0x01<<(11-2*L) ;        // C
    if((q&0x08)==0x08) RAM24[1] |= 0x01<<(10-2*L) ;        // D
    if((q&0x10)==0x10) RAM24[0] |= 0x01<<(10-2*L) ;        // E
    if((q&0x20)==0x20) RAM24[1] |= 0x01<<(13+2*L) ;        // F +
    if((q&0x40)==0x40) RAM24[0] |= 0x01<<(13+2*L) ;        // G +
    if((q&0x80)==0x80) RAM24[0] |= 0x01<<(11-2*L) ;        // M 
}   
     
     
void LCD96map(void){
       int b ;                  
                 
           //  b = 0,1,2, 3,4,5, 6, 7, 8, 9,10,11, 12,13,14,15,16,17, 18,19,20,21,22,23
       char MAP[]={0,1,2, 7,8,9,10,11,12,13,14,15, 17,16,18,19,20,21, 24,25,26,27,28,29};
             // Bits     3,4,5,6,               22,23,            30,31 not used
              LCD->RAM[0*2]  = 0 ;
              LCD->RAM[1*2]  = 0 ;
              LCD->RAM[2*2]  = 0 ;
              LCD->RAM[3*2]  = 0 ;
              for(b=0;b<=23;b++){
                     LCD->RAM[0*2] |=  (RAM24[0]&(1<<b))<<(MAP[b]-b);
                     LCD->RAM[1*2] |=  (RAM24[1]&(1<<b))<<(MAP[b]-b);
                     LCD->RAM[2*2] |=  (RAM24[2]&(1<<b))<<(MAP[b]-b);
                     LCD->RAM[3*2] |=  (RAM24[3]&(1<<b))<<(MAP[b]-b);
              }
}

void PAaft(char PIN, char FUNC){         // Port A alternate function
  GPIOA->MODER       &=  ~(0x03<<(2*PIN)) ;     // Clear Mode mask
  GPIOA->MODER       |=    0x02<<(2*PIN)  ;     // 0=i; 1=O; 2=AltFun; 3=Analog 
  if(PIN<=7){
    GPIOA->AFR[0]    &=  ~(0x0F<<(4*PIN)) ;            // Clear AFR mask
    GPIOA->AFR[0]    |=    FUNC<<(4*PIN) ;             // Alt Func
      } else{
    GPIOA->AFR[1]    &=  ~(0x0F<<(4*(PIN-8))); // Clear AFR mask
    GPIOA->AFR[1]    |=    FUNC<<(4*(PIN-8)) ; // Alt Func
  }
}                                

void PBaft(char PIN, char FUNC){         // Port B alternate function
  GPIOB->MODER       &=  ~(0x03<<(2*PIN)) ;     // Clear Mode mask
  GPIOB->MODER       |=    0x02<<(2*PIN)  ;     // 0=i; 1=O; 2=AltFun; 3=Analog 
  if(PIN<=7){
    GPIOB->AFR[0]    &=  ~(0x0F<<(4*PIN)) ;            // Clear AFR mask
    GPIOB->AFR[0]    |=    FUNC<<(4*PIN) ;             // Alt Func
      } else{
    GPIOB->AFR[1]    &=  ~(0x0F<<(4*(PIN-8))); // Clear AFR mask
    GPIOB->AFR[1]    |=    FUNC<<(4*(PIN-8)) ; // Alt Func
  }
}

void PCaft(char PIN, char FUNC){         // Port C alternate function
       GPIOC->MODER         &=  ~(0x03<<(2*PIN)) ;     // Clear Mode mask
       GPIOC->MODER         |=    0x02<<(2*PIN) ;      // 0=i; 1=O; 2=AltFun; 3=Analog 
       if(PIN<=7){
              GPIOC->AFR[0] &=  ~(0x0F<<(4*PIN)) ;            // Clear AFR mask
              GPIOC->AFR[0]        |=    FUNC<<(4*PIN) ;             // Alt Func
              } else{
              GPIOC->AFR[1]        &=  ~(0x0F<<(4*(PIN-8))); // Clear AFR mask
              GPIOC->AFR[1]        |=    FUNC<<(4*(PIN-8)) ; // Alt Func
              }
}

void LCD96conf(void){
       char i ;
       char Apins[]={1,2,3,8,9,10,15};          // 7 pins
       char Bpins[]={3,4,5,8,9,10,11,12,13,14,15};     // 11 pins
       char Cpins[]={0,1,2,3,6,7,8,9,10,11};           // 10 pins

       //  LCD on Board  Configuration
       RCC->AHBENR  |=  RCC_AHBENR_GPIOAEN ; 
       RCC->AHBENR  |=  RCC_AHBENR_GPIOBEN ;               
       RCC->AHBENR  |=  RCC_AHBENR_GPIOCEN ;               
       for(i=0;i<=6;i++) { PAaft(Apins[i],11);  }
       for(i=0;i<=10;i++){ PBaft(Bpins[i],11);  }
       for(i=0;i<=9;i++) { PCaft(Cpins[i],11);  }

       RCC->APB1ENR  |=  RCC_APB1ENR_LCDEN ;  
       LCD->CR        =      LCD_CR_MUX_SEG | 0x0C | 0x40 ;    // Duty=1/4 Bias=1/3  64-pin !
       LCD->FCR      =  0 ;                    // Reset condition
       LCD->FCR      |=     (4<<22) ;     // PS = 4  (Bits 22,23,24,25)
       LCD->FCR      |=     (1<<18) ;     // DIV = 1  (Bits 18,19,20,21)
       LCD->FCR      |=     (7<<10) ;     // CC = 7  (Bits 10,11,12)
       LCD->FCR      |=     (7<<4) ;      // PON = 7  (Bits 4,5,6)
       LCD->CR       |=     LCD_CR_LCDEN ;
       while( (LCD->SR&LCD_SR_RDY)==0 ); // Wait till ready
}

====================


We can then extend the routine to map all 16 bits or segments for each location.

//  T77.c  STM32 L1 Discovery  LCD on Board

#include "stm32l1xx.h"
int C8[]={0x3F,0x06,0xDB,0xCF,0xE6,0xED,0xFD,0x07,0xFF,0xEF,0x2409} ;    // C8[10] is 'Z'
void LCD96conf(void);
void map16(int q, int L);
void LCD96map(void);
unsigned long RAM24[4];

int main(){
//    int i,j,N,L ;
   
//  Enable LSI for RTC/LCD                                                                                      
        RCC->APB1ENR  |=     RCC_APB1ENR_PWREN ;
    PWR->CR       |=     PWR_CR_DBP ;
    RCC->CSR      |=     RCC_CSR_LSION ;
    while( (RCC->CSR&RCC_CSR_LSIRDY)==0 );   // Wait till LSE Ready   
    RCC->CSR      &=     ~RCC_CSR_RTCSEL ;   // Mask
    RCC->CSR      |=     RCC_CSR_RTCSEL_LSI ;    
     
    LCD96conf();

// Testing LCD 
    RAM24[0] = 0 ;
    RAM24[1] = 0 ;
    RAM24[2] = 0 ;
    RAM24[3] = 0 ;
    map16(C8[10], 0);    // Test a letter
    LCD96map();
    LCD->SR    |=    LCD_SR_UDR ;
    while( (LCD->SR&LCD_SR_UDD)==0 );

    while(1);

}

void map16(int q, int L){            // L=0 : Rightmost location
    if((q&0x01)==0x01) RAM24[1] |= 0x01<<(12+2*L) ;        // A +
    if((q&0x02)==0x02) RAM24[0] |= 0x01<<(12+2*L) ;        // B +
    if((q&0x04)==0x04) RAM24[1] |= 0x01<<(11-2*L) ;        // C
    if((q&0x08)==0x08) RAM24[1] |= 0x01<<(10-2*L) ;        // D
    if((q&0x10)==0x10) RAM24[0] |= 0x01<<(10-2*L) ;        // E
    if((q&0x20)==0x20) RAM24[1] |= 0x01<<(13+2*L) ;        // F +
    if((q&0x40)==0x40) RAM24[0] |= 0x01<<(13+2*L) ;        // G +
    if((q&0x80)==0x80) RAM24[0] |= 0x01<<(11-2*L) ;        // M 
    if((q&0x0100)==0x0100) RAM24[3] |= 0x01<<(13+2*L) ;        //  
    if((q&0x0200)==0x0200) RAM24[3] |= 0x01<<(12+2*L) ;        //  
    if((q&0x0400)==0x0400) RAM24[2] |= 0x01<<(12+2*L) ;        //  
    if((q&0x0800)==0x0800) RAM24[3] |= 0x01<<(10-2*L) ;        //  
    if((q&0x1000)==0x1000) RAM24[2] |= 0x01<<(10-2*L) ;        //  
    if((q&0x2000)==0x2000) RAM24[2] |= 0x01<<(13+2*L) ;        //  
    if((q&0x4000)==0x4000) RAM24[3] |= 0x01<<(11-2*L) ;        //  
    if((q&0x8000)==0x8000) RAM24[2] |= 0x01<<(11-2*L) ;        //  
}   

     
     
void LCD96map(void){
       int b ;                  
                 
           //  b = 0,1,2, 3,4,5, 6, 7, 8, 9,10,11, 12,13,14,15,16,17, 18,19,20,21,22,23
       char MAP[]={0,1,2, 7,8,9,10,11,12,13,14,15, 17,16,18,19,20,21, 24,25,26,27,28,29};
             // Bits     3,4,5,6,               22,23,            30,31 not used
              LCD->RAM[0*2]  = 0 ;
              LCD->RAM[1*2]  = 0 ;
              LCD->RAM[2*2]  = 0 ;
              LCD->RAM[3*2]  = 0 ;
              for(b=0;b<=23;b++){
                     LCD->RAM[0*2] |=  (RAM24[0]&(1<<b))<<(MAP[b]-b);
                     LCD->RAM[1*2] |=  (RAM24[1]&(1<<b))<<(MAP[b]-b);
                     LCD->RAM[2*2] |=  (RAM24[2]&(1<<b))<<(MAP[b]-b);
                     LCD->RAM[3*2] |=  (RAM24[3]&(1<<b))<<(MAP[b]-b);
              }
}

void PAaft(char PIN, char FUNC){         // Port A alternate function
  GPIOA->MODER       &=  ~(0x03<<(2*PIN)) ;     // Clear Mode mask
  GPIOA->MODER       |=    0x02<<(2*PIN)  ;     // 0=i; 1=O; 2=AltFun; 3=Analog 
  if(PIN<=7){
    GPIOA->AFR[0]    &=  ~(0x0F<<(4*PIN)) ;            // Clear AFR mask
    GPIOA->AFR[0]    |=    FUNC<<(4*PIN) ;             // Alt Func
      } else{
    GPIOA->AFR[1]    &=  ~(0x0F<<(4*(PIN-8))); // Clear AFR mask
    GPIOA->AFR[1]    |=    FUNC<<(4*(PIN-8)) ; // Alt Func
  }
}                                

void PBaft(char PIN, char FUNC){         // Port B alternate function
  GPIOB->MODER       &=  ~(0x03<<(2*PIN)) ;     // Clear Mode mask
  GPIOB->MODER       |=    0x02<<(2*PIN)  ;     // 0=i; 1=O; 2=AltFun; 3=Analog 
  if(PIN<=7){
    GPIOB->AFR[0]    &=  ~(0x0F<<(4*PIN)) ;            // Clear AFR mask
    GPIOB->AFR[0]    |=    FUNC<<(4*PIN) ;             // Alt Func
      } else{
    GPIOB->AFR[1]    &=  ~(0x0F<<(4*(PIN-8))); // Clear AFR mask
    GPIOB->AFR[1]    |=    FUNC<<(4*(PIN-8)) ; // Alt Func
  }
}

void PCaft(char PIN, char FUNC){         // Port C alternate function
       GPIOC->MODER         &=  ~(0x03<<(2*PIN)) ;     // Clear Mode mask
       GPIOC->MODER         |=    0x02<<(2*PIN) ;      // 0=i; 1=O; 2=AltFun; 3=Analog 
       if(PIN<=7){
              GPIOC->AFR[0] &=  ~(0x0F<<(4*PIN)) ;            // Clear AFR mask
              GPIOC->AFR[0]        |=    FUNC<<(4*PIN) ;             // Alt Func
              } else{
              GPIOC->AFR[1]        &=  ~(0x0F<<(4*(PIN-8))); // Clear AFR mask
              GPIOC->AFR[1]        |=    FUNC<<(4*(PIN-8)) ; // Alt Func
              }
}

void LCD96conf(void){
       char i ;
       char Apins[]={1,2,3,8,9,10,15};          // 7 pins
       char Bpins[]={3,4,5,8,9,10,11,12,13,14,15};     // 11 pins
       char Cpins[]={0,1,2,3,6,7,8,9,10,11};           // 10 pins

       //  LCD on Board  Configuration
       RCC->AHBENR  |=  RCC_AHBENR_GPIOAEN ; 
       RCC->AHBENR  |=  RCC_AHBENR_GPIOBEN ;               
       RCC->AHBENR  |=  RCC_AHBENR_GPIOCEN ;               
       for(i=0;i<=6;i++) { PAaft(Apins[i],11);  }
       for(i=0;i<=10;i++){ PBaft(Bpins[i],11);  }
       for(i=0;i<=9;i++) { PCaft(Cpins[i],11);  }

       RCC->APB1ENR  |=  RCC_APB1ENR_LCDEN ;  
       LCD->CR        =      LCD_CR_MUX_SEG | 0x0C | 0x40 ;    // Duty=1/4 Bias=1/3  64-pin !
       LCD->FCR      =  0 ;                    // Reset condition
       LCD->FCR      |=     (4<<22) ;     // PS = 4  (Bits 22,23,24,25)
       LCD->FCR      |=     (1<<18) ;     // DIV = 1  (Bits 18,19,20,21)
       LCD->FCR      |=     (7<<10) ;     // CC = 7  (Bits 10,11,12)
       LCD->FCR      |=     (7<<4) ;      // PON = 7  (Bits 4,5,6)
       LCD->CR       |=     LCD_CR_LCDEN ;
       while( (LCD->SR&LCD_SR_RDY)==0 ); // Wait till ready
}

====================


But to code the segments for each letter may take some time. 
So let us just display one segment at a time.
 
//  T78.c  STM32 L1 Discovery  LCD on Board

#include "stm32l1xx.h"
int C8[]={0x3F,0x06,0xDB,0xCF,0xE6,0xED,0xFD,0x07,0xFF,0xEF,0x1500} ;    // C8[10] is 'Y'
void LCD96conf(void);
void map16(int q, int L);
void LCD96map(void);
unsigned long RAM24[4];

int main(){
    int i,j,S,L ;
   
//  Enable LSI for RTC/LCD                                                                                      
        RCC->APB1ENR  |=     RCC_APB1ENR_PWREN ;
    PWR->CR       |=     PWR_CR_DBP ;
    RCC->CSR      |=     RCC_CSR_LSION ;
    while( (RCC->CSR&RCC_CSR_LSIRDY)==0 );   // Wait till LSE Ready   
    RCC->CSR      &=     ~RCC_CSR_RTCSEL ;   // Mask
    RCC->CSR      |=     RCC_CSR_RTCSEL_LSI ;    
     
    LCD96conf();

// Testing LCD 
    RAM24[0] = 0 ;
    RAM24[1] = 0 ;
    RAM24[2] = 0 ;
    RAM24[3] = 0 ;
    map16(C8[10], 0);    // Test a letter
    LCD96map();
    LCD->SR    |=    LCD_SR_UDR ;
    while( (LCD->SR&LCD_SR_UDD)==0 );

        S = -1 ;
        L = 0 ;


    while(1){
                RAM24[0] = 0 ;
                RAM24[1] = 0 ;
                RAM24[2] = 0 ;
                RAM24[3] = 0 ;
                S++;
                if(S==16){
                    S = 0 ;
                    L++;
                    if(L==6) L = 0 ;
                }
                map16(0x01<<S,L);    //   
                LCD96map();
                LCD->SR    |=    LCD_SR_UDR ;
                while( (LCD->SR&LCD_SR_UDD)==0 );
                for(i=0;i<=200;i++){ for(j=0;j<=1000;j++);}
       }
   
}

void map16(int q, int L){            // L=0 : Rightmost location
    if((q&0x01)==0x01) RAM24[1] |= 0x01<<(12+2*L) ;        // A +
    if((q&0x02)==0x02) RAM24[0] |= 0x01<<(12+2*L) ;        // B +
    if((q&0x04)==0x04) RAM24[1] |= 0x01<<(11-2*L) ;        // C
    if((q&0x08)==0x08) RAM24[1] |= 0x01<<(10-2*L) ;        // D
    if((q&0x10)==0x10) RAM24[0] |= 0x01<<(10-2*L) ;        // E
    if((q&0x20)==0x20) RAM24[1] |= 0x01<<(13+2*L) ;        // F +
    if((q&0x40)==0x40) RAM24[0] |= 0x01<<(13+2*L) ;        // G +
    if((q&0x80)==0x80) RAM24[0] |= 0x01<<(11-2*L) ;        // M 
    if((q&0x0100)==0x0100) RAM24[3] |= 0x01<<(13+2*L) ;        //  
    if((q&0x0200)==0x0200) RAM24[3] |= 0x01<<(12+2*L) ;        //  
    if((q&0x0400)==0x0400) RAM24[2] |= 0x01<<(12+2*L) ;        //  
    if((q&0x0800)==0x0800) RAM24[3] |= 0x01<<(10-2*L) ;        //  
    if((q&0x1000)==0x1000) RAM24[2] |= 0x01<<(10-2*L) ;        //  
    if((q&0x2000)==0x2000) RAM24[2] |= 0x01<<(13+2*L) ;        //  
    if((q&0x4000)==0x4000) RAM24[3] |= 0x01<<(11-2*L) ;        //  
    if((q&0x8000)==0x8000) RAM24[2] |= 0x01<<(11-2*L) ;        //  
}   

     
     
void LCD96map(void){
       int b ;                  
                 
           //  b = 0,1,2, 3,4,5, 6, 7, 8, 9,10,11, 12,13,14,15,16,17, 18,19,20,21,22,23
       char MAP[]={0,1,2, 7,8,9,10,11,12,13,14,15, 17,16,18,19,20,21, 24,25,26,27,28,29};
             // Bits     3,4,5,6,               22,23,            30,31 not used
              LCD->RAM[0*2]  = 0 ;
              LCD->RAM[1*2]  = 0 ;
              LCD->RAM[2*2]  = 0 ;
              LCD->RAM[3*2]  = 0 ;
              for(b=0;b<=23;b++){
                     LCD->RAM[0*2] |=  (RAM24[0]&(1<<b))<<(MAP[b]-b);
                     LCD->RAM[1*2] |=  (RAM24[1]&(1<<b))<<(MAP[b]-b);
                     LCD->RAM[2*2] |=  (RAM24[2]&(1<<b))<<(MAP[b]-b);
                     LCD->RAM[3*2] |=  (RAM24[3]&(1<<b))<<(MAP[b]-b);
              }
}

void PAaft(char PIN, char FUNC){         // Port A alternate function
  GPIOA->MODER       &=  ~(0x03<<(2*PIN)) ;     // Clear Mode mask
  GPIOA->MODER       |=    0x02<<(2*PIN)  ;     // 0=i; 1=O; 2=AltFun; 3=Analog 
  if(PIN<=7){
    GPIOA->AFR[0]    &=  ~(0x0F<<(4*PIN)) ;            // Clear AFR mask
    GPIOA->AFR[0]    |=    FUNC<<(4*PIN) ;             // Alt Func
      } else{
    GPIOA->AFR[1]    &=  ~(0x0F<<(4*(PIN-8))); // Clear AFR mask
    GPIOA->AFR[1]    |=    FUNC<<(4*(PIN-8)) ; // Alt Func
  }
}                                

void PBaft(char PIN, char FUNC){         // Port B alternate function
  GPIOB->MODER       &=  ~(0x03<<(2*PIN)) ;     // Clear Mode mask
  GPIOB->MODER       |=    0x02<<(2*PIN)  ;     // 0=i; 1=O; 2=AltFun; 3=Analog 
  if(PIN<=7){
    GPIOB->AFR[0]    &=  ~(0x0F<<(4*PIN)) ;            // Clear AFR mask
    GPIOB->AFR[0]    |=    FUNC<<(4*PIN) ;             // Alt Func
      } else{
    GPIOB->AFR[1]    &=  ~(0x0F<<(4*(PIN-8))); // Clear AFR mask
    GPIOB->AFR[1]    |=    FUNC<<(4*(PIN-8)) ; // Alt Func
  }
}

void PCaft(char PIN, char FUNC){         // Port C alternate function
       GPIOC->MODER         &=  ~(0x03<<(2*PIN)) ;     // Clear Mode mask
       GPIOC->MODER         |=    0x02<<(2*PIN) ;      // 0=i; 1=O; 2=AltFun; 3=Analog 
       if(PIN<=7){
              GPIOC->AFR[0] &=  ~(0x0F<<(4*PIN)) ;            // Clear AFR mask
              GPIOC->AFR[0]        |=    FUNC<<(4*PIN) ;             // Alt Func
              } else{
              GPIOC->AFR[1]        &=  ~(0x0F<<(4*(PIN-8))); // Clear AFR mask
              GPIOC->AFR[1]        |=    FUNC<<(4*(PIN-8)) ; // Alt Func
              }
}

void LCD96conf(void){
       char i ;
       char Apins[]={1,2,3,8,9,10,15};          // 7 pins
       char Bpins[]={3,4,5,8,9,10,11,12,13,14,15};     // 11 pins
       char Cpins[]={0,1,2,3,6,7,8,9,10,11};           // 10 pins

       //  LCD on Board  Configuration
       RCC->AHBENR  |=  RCC_AHBENR_GPIOAEN ; 
       RCC->AHBENR  |=  RCC_AHBENR_GPIOBEN ;               
       RCC->AHBENR  |=  RCC_AHBENR_GPIOCEN ;               
       for(i=0;i<=6;i++) { PAaft(Apins[i],11);  }
       for(i=0;i<=10;i++){ PBaft(Bpins[i],11);  }
       for(i=0;i<=9;i++) { PCaft(Cpins[i],11);  }

       RCC->APB1ENR  |=  RCC_APB1ENR_LCDEN ;  
       LCD->CR        =      LCD_CR_MUX_SEG | 0x0C | 0x40 ;    // Duty=1/4 Bias=1/3  64-pin !
       LCD->FCR      =  0 ;                    // Reset condition
       LCD->FCR      |=     (4<<22) ;     // PS = 4  (Bits 22,23,24,25)
       LCD->FCR      |=     (1<<18) ;     // DIV = 1  (Bits 18,19,20,21)
       LCD->FCR      |=     (7<<10) ;     // CC = 7  (Bits 10,11,12)
       LCD->FCR      |=     (7<<4) ;      // PON = 7  (Bits 4,5,6)
       LCD->CR       |=     LCD_CR_LCDEN ;
       while( (LCD->SR&LCD_SR_RDY)==0 ); // Wait till ready

====================


That should be enough for the time being.
 

1 comment: