Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

STM32F4-Discovery lcd 4*20

Status
Not open for further replies.

dariush_abbasi

Member level 3
Joined
Oct 2, 2010
Messages
63
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,288
Activity points
1,682
Hi everybody,
I want to interface a 4*20 character lcd to this board,is anyone has the LCD_4bit.c?
I have that file for stm32f103 but i can't change it for stm32f407.
Code:
/*----------------------------------------------------------------------------
 * Name:    LCD_4bit.c
 * Purpose: Functions for 2 line 16 character Text LCD (4-bit interface)
 *                connected on MCBSTM32 evaluation board 
 * Version: V1.10
 *----------------------------------------------------------------------------
 * This file is part of the uVision/ARM development tools.
 * This software may only be used under the terms of a valid, current,
 * end user licence from KEIL for a compatible version of KEIL software
 * development tools. Nothing else gives you the right to use this software.
 *
 * Copyright (c) 2005-2007 Keil Software. All rights reserved.
 *---------------------------------------------------------------------------*/

#include "stm32f4_discovery.h"          /* STM32F10x Library Definitions      */

/*********************** Hardware specific configuration **********************/

/*------------------------- Speed dependant settings -------------------------*/

/* If processor works on high frequency delay has to be increased, it can be 
   increased by factor 2^N by this constant                                   */
#define DELAY_2N     0

/*------------------------- Text LCD size definitions ------------------------*/

#define LineLen     16                  /* Width (in characters)              */
#define NumLines     2                  /* Hight (in lines)                   */

/*-------------------- LCD interface hardware definitions --------------------*/

/* PINS: 
   - DB4 = PC3
   - DB5 = PC2
   - DB6 = PC1
   - DB7 = PC0
   - E   = PC10
   - RW  = PC11
   - RS  = PC12                                                               */

#define PIN_E                 (   1 << 10)
#define PIN_RW                (   1 << 11)
#define PIN_RS                (   1 << 12)
#define PINS_CTRL             (0x07 << 10)
#define PINS_DATA             (0x0F <<  0)
#define PINS_ALL              (PINS_CTRL | PINS_DATA)

const unsigned int SWAP_DATA[16] = { 0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE, 
                                     0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF};

/* Enable Clock for peripheral driving LCD pins                               */
#define LCD_CLOCK_EN         (RCC->APB2ENR |= (1 << 4)); // enable clock for GPIOC

/* pin E  setting to 0 or 1                                                   */
#define LCD_E(x)              GPIOC->ODR = (GPIOC->ODR & ~PIN_E)  | (x ? PIN_E : 0);

/* pin RW setting to 0 or 1                                                   */
#define LCD_RW(x)             GPIOC->ODR = (GPIOC->ODR & ~PIN_RW) | (x ? PIN_RW : 0);

/* pin RS setting to 0 or 1                                                   */
#define LCD_RS(x)             GPIOC->ODR = (GPIOC->ODR & ~PIN_RS) | (x ? PIN_RS : 0);

/* Reading DATA pins                                                          */
#define LCD_DATA_IN           SWAP_DATA[(((GPIOC->IDR & PINS_DATA) >> 0) & 0x0F)]

/* Writing value to DATA pins                                                 */
#define LCD_DATA_OUT(x)       GPIOC->ODR = (GPIOC->ODR & ~PINS_DATA) | ((SWAP_DATA[x]) << 0);

/* Setting all pins to output mode                                            */
#define LCD_ALL_DIR_OUT       GPIOC->CRL = (GPIOC->CRL & 0xFFFF0000) | 0x00003333; \
                              GPIOC->CRH = (GPIOC->CRH & 0xFFF000FF) | 0x00033300;
							  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
 
/* Setting DATA pins to input mode                                            */
#define LCD_DATA_DIR_IN       GPIOC->CRL = (GPIOC->CRL & 0xFFFF0000) | 0x00004444;

/* Setting DATA pins to output mode                                           */
#define LCD_DATA_DIR_OUT      GPIOC->CRL = (GPIOC->CRL & 0xFFFF0000) | 0x00003333;

/******************************************************************************/


/* 8 user defined characters to be loaded into CGRAM (used for bargraph)      */
const char UserFont[8][8] = {
  { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
  { 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10 },
  { 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18 },
  { 0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C },
  { 0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E },
  { 0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F },
  { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
  { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }
};


/************************ Global function definitions *************************/


/*******************************************************************************
* Delay in while loop cycles                                                   *
*   Parameter:    cnt:    number of while cycles to delay                      *
*   Return:                                                                    *
*******************************************************************************/

static void delay (int cnt)
{
  cnt <<= DELAY_2N;

  while (cnt--);
}


/*******************************************************************************
* Read status of LCD controller                                                *
*   Parameter:    none                                                         *
*   Return:       Status byte contains busy flag and address pointer           *
*******************************************************************************/

static unsigned char lcd_read_status (void)
{
  unsigned char status;

  LCD_DATA_DIR_IN
  LCD_RS(0)
  LCD_RW(1)
  delay(10);
  LCD_E(1)
  delay(10);
  status  = LCD_DATA_IN << 4;
  LCD_E(0)
  delay(10);
  LCD_E(1)
  delay(10);
  status |= LCD_DATA_IN;
  LCD_E(0)
  LCD_DATA_DIR_OUT
  return (status);
}


/*******************************************************************************
* Wait until LCD controller busy flag is 0                                     *
*   Parameter:                                                                 *
*   Return:       Status byte of LCD controller (busy + address)               *
*******************************************************************************/

static unsigned char wait_while_busy (void)
{
  unsigned char status;

  do  {
    status = lcd_read_status();
  }  while (status & 0x80);             /* Wait for busy flag                 */

  return (status);
}


/*******************************************************************************
* Write 4-bits to LCD controller                                               *
*   Parameter:    c:      command to be written                                *
*   Return:                                                                    *
*******************************************************************************/

void lcd_write_4bit (unsigned char c)
{
  LCD_RW(0)
  LCD_E(1)
  LCD_DATA_OUT(c&0x0F)
  delay(10);
  LCD_E(0)
  delay(10);
}


/*******************************************************************************
* Write command to LCD controller                                              *
*   Parameter:    c:      command to be written                                *
*   Return:                                                                    *
*******************************************************************************/

void lcd_write_cmd (unsigned char c)
{
  wait_while_busy();

  LCD_RS(0)
  lcd_write_4bit (c>>4);
  lcd_write_4bit (c);
}


/*******************************************************************************
* Write data to LCD controller                                                 *
*   Parameter:    c:      data to be written                                   *
*   Return:                                                                    *
*******************************************************************************/

static void lcd_write_data (unsigned char c)
{
  wait_while_busy();

  LCD_RS(1)
  lcd_write_4bit (c>>4);
  lcd_write_4bit (c);
}


/*******************************************************************************
* Print Character to current cursor position                                   *
*   Parameter:    c:      character to be printed                              *
*   Return:                                                                    *
*******************************************************************************/

void lcd_putchar (char c)
{ 
  lcd_write_data (c);
}


/*******************************************************************************
* Initialize the LCD controller                                                *
*   Parameter:                                                                 *
*   Return:                                                                    *
*******************************************************************************/

void lcd_init (void)
{ 
  int i;
  char const *p;

  LCD_CLOCK_EN                          /* Enable clock for peripheral        */

  /* Set all pins for LCD as outputs                                          */
  LCD_ALL_DIR_OUT

  delay (15000);
  LCD_RS(0)
  lcd_write_4bit (0x3);                 /* Select 4-bit interface             */
  delay (4100);
  lcd_write_4bit (0x3);
  delay (100);
  lcd_write_4bit (0x3);
  lcd_write_4bit (0x2);

  lcd_write_cmd (0x28);                 /* 2 lines, 5x8 character matrix      */
  lcd_write_cmd (0x0C);                 /* Display ctrl:Disp=ON,Curs/Blnk=OFF */
  lcd_write_cmd (0x06);                 /* Entry mode: Move right, no shift   */

  /* Load user-specific characters into CGRAM                                 */
  lcd_write_cmd(0x40);                  /* Set CGRAM address counter to 0     */
  p = &UserFont[0][0];
  for (i = 0; i < sizeof(UserFont); i++, p++)
    lcd_putchar (*p);

  lcd_write_cmd(0x80);                  /* Set DDRAM address counter to 0     */
}



/*******************************************************************************
* Set cursor position on LCD display                                           *
*   Parameter:    column: column position                                      *
*                 line:   line position                                        *
*   Return:                                                                    *
*******************************************************************************/

void set_cursor (int column, int line)
{
  unsigned char address;

  address = (line * 40) + column;
  address = 0x80 + (address & 0x7F);
  lcd_write_cmd(address);               /* Set DDRAM address counter to 0     */
}

/*******************************************************************************
* Clear the LCD display                                                        *
*   Parameter:                                                                 *
*   Return:                                                                    *
*******************************************************************************/

void lcd_clear (void)
{
  lcd_write_cmd(0x01);                  /* Display clear                      */
  set_cursor (0, 0);
}


/*******************************************************************************
* Print sting to LCD display                                                   *
*   Parameter:    string: pointer to output string                             *
*   Return:                                                                    *
*******************************************************************************/

void lcd_print (char *string)
{
  while (*string)  {
    lcd_putchar (*string++);
  }
}


/*******************************************************************************
* Print a bargraph to LCD display                                              *
*   Parameter:     val:  value 0..100 %                                        *
*                  size: size of bargraph 1..16                                *
*   Return:                                                                    *
*******************************************************************************/
void lcd_bargraph (int value, int size) {
   int i;

   value = value * size / 20;            /* Display matrix 5 x 8 pixels       */
   for (i = 0; i < size; i++) {
      if (value > 5) {
         lcd_putchar (0x05);
         value -= 5;
      }
      else {
         lcd_putchar (value);
         break;
      }
   }
}


/*******************************************************************************
* Display bargraph on LCD display                                              *
*   Parameter:     pos_x: horizontal position of bargraph start                *
*                  pos_y: vertical position of bargraph                        *
*                  value: size of bargraph active field (in pixels)            *
*   Return:                                                                    *
*******************************************************************************/

void lcd_bargraphXY (int pos_x, int pos_y, int value) {
  int i;

  set_cursor (pos_x, pos_y);
  for (i = 0; i < 16; i++)  {
    if (value > 5) {
      lcd_putchar (0x05);
      value -= 5;
    } else {
      lcd_putchar (value);
      while (i++ < 16) lcd_putchar (0);
    }
  }
}

/******************************************************************************/


At least these lines must be changed,what should i do?

Code:
/* Setting all pins to output mode                                            */
#define LCD_ALL_DIR_OUT       GPIOC->CRL = (GPIOC->CRL & 0xFFFF0000) | 0x00003333; \
                              GPIOC->CRH = (GPIOC->CRH & 0xFFF000FF) | 0x00033300;
							  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
 
/* Setting DATA pins to input mode                                            */
#define LCD_DATA_DIR_IN       GPIOC->CRL = (GPIOC->CRL & 0xFFFF0000) | 0x00004444;

/* Setting DATA pins to output mode                                           */
#define LCD_DATA_DIR_OUT      GPIOC->CRL = (GPIOC->CRL & 0xFFFF0000) | 0x00003333;

Thanks a lot in advance.
 

alex_r

Member level 4
Joined
May 5, 2012
Messages
68
Helped
21
Reputation
42
Reaction score
21
Trophy points
1,288
Location
Treviso Italy
Activity points
1,622
You can try this:
Code:
* Setting all pins to output mode                                            */
#define LCD_ALL_DIR_OUT       GPIOC->OTYPER &= 0xFFFFE3F0; \  
                              GPIOC->MODER = (GPIOc->MODER & 0xFC0FFF00) | 0x01500055;

/* Setting DATA pins to input mode                                            */
#define LCD_DATA_DIR_IN       GPIOC->MODER &= 0xFFFFFF00;

/* Setting DATA pins to output mode                                           */
#define LCD_DATA_DIR_OUT      GPIOC->MODER = (GPIOC->MODER & 0xFFFFFF00) | 0x55;
 

dariush_abbasi

Member level 3
Joined
Oct 2, 2010
Messages
63
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,288
Activity points
1,682
Hi,
Thanks a lot Dear alex_r,
I will check that.

---------- Post added at 06:11 ---------- Previous post was at 05:11 ----------

I can't compile the code.
It says something strange from this line of code:
LCD_4bit.c(71): error: #18: expected a ")"
Code:
GPIOC->MODER = (GPIOC->MODER & 0xFC0FFF00) | 0x01500055;
 

alex_r

Member level 4
Joined
May 5, 2012
Messages
68
Helped
21
Reputation
42
Reaction score
21
Trophy points
1,288
Location
Treviso Italy
Activity points
1,622
Hi

The only reference to LCD_ALL_DIR_OUT seem to be in LCD_Init(), so try to put the two line direcly.

Code:
void lcd_init (void)
{ 
  int i;
  char const *p;

  LCD_CLOCK_EN                          /* Enable clock for peripheral        */

  /* Set all pins for LCD as outputs                                          */
  GPIOC->OTYPER &= 0xFFFFE3F0;  
  GPIOC->MODER = (GPIOc->MODER & 0xFC0FFF00) | 0x01500055;

  delay (15000);
  LCD_RS(0)
  lcd_write_4bit (0x3);                 /* Select 4-bit interface             */

  ...........
  ...........
 
Last edited:

dariush_abbasi

Member level 3
Joined
Oct 2, 2010
Messages
63
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,288
Activity points
1,682
Hi,
Thanks again for your reply.
The code compiled but the LCD does not work.
Do you have the board and or maybe the stm32f4 chip ?
Did you get response from the stmf4 chip/board and LCD?
Many regards.
 

alex_r

Member level 4
Joined
May 5, 2012
Messages
68
Helped
21
Reputation
42
Reaction score
21
Trophy points
1,288
Location
Treviso Italy
Activity points
1,622
Yes, I have the STM32F4-discovery but no a LCD 4x20.

I compare STM32F1 and STM32F4 reference manual in GPIO register section.
You can try also using stm32f4_dsp_stdperiph_lib function to setting GPIO pin instead directly access the GPIO register.

You can make 3 simply function equivalent to the define (it is slower but surely work)
Another hint: try to increase twice or more the delay time in delay() function
 

dariush_abbasi

Member level 3
Joined
Oct 2, 2010
Messages
63
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,288
Activity points
1,682
I check it with a 2*16 LCD and also increase the delay time but...
Thanks for your suggestions.
 

alex_r

Member level 4
Joined
May 5, 2012
Messages
68
Helped
21
Reputation
42
Reaction score
21
Trophy points
1,288
Location
Treviso Italy
Activity points
1,622
Hi,
Try insert this code and delete the old define

Code:
void lcd_all_dir_out(void)
{
  GPIO_InitTypeDef  GPIO_InitStructure;

  /* GPIOC Periph clock enable */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);

  /* Configure PC12, PC11, PC10 and PC3, PC2 ,PC1,PC0 in output pushpull mode */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_11| GPIO_Pin_10| GPIO_Pin_3| GPIO_Pin_2| GPIO_Pin_1| GPIO_Pin_0;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOC, &GPIO_InitStructure);
}

void lcd_data_dir_out(void)
{
  GPIO_InitTypeDef  GPIO_InitStructure;

  /* Configure PC3, PC2 ,PC1,PC0 in output pushpull mode */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3| GPIO_Pin_2| GPIO_Pin_1| GPIO_Pin_0;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOC, &GPIO_InitStructure);
}

void lcd_data_dir_in(void)
{
  GPIO_InitTypeDef  GPIO_InitStructure;

  /* Configure PC3, PC2 ,PC1,PC0 in input mode */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3| GPIO_Pin_2| GPIO_Pin_1| GPIO_Pin_0;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOC, &GPIO_InitStructure);
}

#define LCD_ALL_DIR_OUT   lcd_all_dir_out();
#define LCD_DATA_DIR_IN   lcd_data_dir_in();
#define LCD_DATA_DIR_OUT  lcd_data_dir_out();

If it not work the issue isn't in GPIO setting.
Can be probably a conflict with the other device connected on the GPIOC pin. (see STMF4-discovery UM)
 
Last edited:

dariush_abbasi

Member level 3
Joined
Oct 2, 2010
Messages
63
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,288
Activity points
1,682
Hi dear alex_r,
No,it doesn't work,i think some where else in the code must also be changed.
Another question:
If you look at the examples of board you find the TIM_PWM_Input example,in that example there is a data type named __IO uint16_t .
Would you please tell me what kind of data type is this and also the reason for its usage here?
Thanks.

---------- Post added at 18:11 ---------- Previous post was at 17:51 ----------

I can't change this data type to for example int or ....
and also i can't do the following :
Code:
__IO uint16_t DutyCycle = 0;
DutyCycle = DutyCycle - 0.6;//the program halts here
the program halts.
 

dariush_abbasi

Member level 3
Joined
Oct 2, 2010
Messages
63
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,288
Activity points
1,682
Thanks.
I want to have some modification to DutyCycle,how can i do that?
I want something like double or long doule for DutyCycle ,but if i change the __IO uint16_t the code no longer works!
what should i do?
what data type should i use?

---------- Post added at 19:23 ---------- Previous post was at 19:20 ----------

I want to have some floating point modification like:
DutyCycle = DutyCycle / 0.03;
DutyCycle2 = DutyCycle * 1.2;
.....
 

alex_r

Member level 4
Joined
May 5, 2012
Messages
68
Helped
21
Reputation
42
Reaction score
21
Trophy points
1,288
Location
Treviso Italy
Activity points
1,622
DutyCycle is itself modified in TIM4 Irq Handler.
If you want make some calculation starting with its value simply copy it in another variable
Code:
float FloatDutyCycle;

FloatDutyCycle=(float) DutyCycle;  // this give you a value in range 0.0-100.0
// process the value as you prefer //
 

dariush_abbasi

Member level 3
Joined
Oct 2, 2010
Messages
63
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,288
Activity points
1,682
Yes,i'm using keil with a 2.4 tft lcd.
The code compiles successfully but when i have any modification such as type casting as you said the processor hangs and i have nothing on lcd and the red led on the board turns on!
Actually,i have no other option to see the dutycycle.
Would you please give me your email ?
I can send you the code but you haven't got that lcd.
Do you have any kind of lcd or indicator connected to your board?
I get frustrated.
 

dariush_abbasi

Member level 3
Joined
Oct 2, 2010
Messages
63
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,288
Activity points
1,682
Thanks a lot.
Can i send the code for you?!!because i 've connected a SMT160 Temperature sensor to PB.07(TIM4 CC2) and i think you don't have this sensor at your disposal to check my code.
Now,i'm trying to check the code without the sensor and i will tell you the result.

---------- Post added at 21:38 ---------- Previous post was at 21:31 ----------

The code works without connecting the sensor but not with sensor.
Do you think that there must be some kind of conflict with the board and sensor connected to PB.07?
 

alex_r

Member level 4
Joined
May 5, 2012
Messages
68
Helped
21
Reputation
42
Reaction score
21
Trophy points
1,288
Location
Treviso Italy
Activity points
1,622
No I don't have a SMT160 to try.
Can you place a breakpoint after reading the dutycycle, and step by step see how you code fail ?
 

dariush_abbasi

Member level 3
Joined
Oct 2, 2010
Messages
63
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,288
Activity points
1,682
I can't debug,keil says "no stlink detected".
The reason for working the code without connecting the sensor is that it doesn't enter this block:
Code:
  if (IC2Value != 0)
  {
    /* Duty cycle computation */
    DutyCycle = (TIM_GetCapture1(TIM4) * 100) / IC2Value;
	DutyCycle = DutyCycle * 1.2;// or this expression[B] FloatDutyCycle=(float) DutyCycle; [/B]

    /* Frequency computation 
       TIM4 counter clock = (RCC_Clocks.HCLK_Frequency)/2 */

    Frequency = (RCC_Clocks.HCLK_Frequency)/2 / IC2Value;
	Frequency = Frequency * 10000;//these modification(integer type) works fine.
	

  }


---------- Post added at 22:22 ---------- Previous post was at 22:07 ----------

I checked the board datasheet,nothing attached to PB.07.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Top