T02 - LED display driver

Header with definitions: mam.zip

4-digit LED display is connected to microcontroler by the use of two serial-in shift registers with output latches SN74LS595. To display any information on the display it is necessary to send two bytes:

  • 1st byte represents individual segments of single LED display (D7..D0)
  • 2nd byte represents address of digit (A7..A0)

Used pins of microcontroller:

  • GPIOA9 - serial data
  • GPIOA8 - clock
  • GPIOB5 - latch

Figure 1 shows time diagram of communication between microcontroller and LED display. Bits are sent starting from MSB.

Example of serial data sequence (two bytes) to show number 0 on 1st digit (from the left): 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1

shift register (1B):

     output (8 bits)
  ^   ^   ^   ^   ^   ^   ^   ^
| x | x | x | x | x | x | x | x | < input data  (1 bit) GPIOA9
                                  < input clock (1 bit) GPIOA8
                                  < input latch (1 bit) GPIOB5

00110011 -> store it in register memory
   
series of bits on data input (GPIOA9)
clock (change from 0->1 on GPIOA8) at the moment, when value on the data input is set
   
set 0 to data input  | x | x | x | x | x | x | x | x | < 0
clock                | x | x | x | x | x | x | x | 0 |
set 0 to data input  | x | x | x | x | x | x | x | 0 | < 0
clock                | x | x | x | x | x | x | 0 | 0 |
set 1 to data input  | x | x | x | x | x | x | 0 | 0 | < 1
clock                | x | x | x | x | x | 0 | 0 | 1 |
set 1 to data input  | x | x | x | x | x | 0 | 0 | 1 | < 1
clock                | x | x | x | x | 0 | 0 | 1 | 1 |
 ...
set 1 to data input  | x | 0 | 0 | 1 | 1 | 0 | 0 | 1 | < 1
clock                | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 |
latch - change from 0->1 propagates 1B word stored in memory to the output of register
   
1 byte representation of 0/1
0: 00000000
1: 00000001
byte to serialize: X
bit to be set on the GPIOA9: bit
   
for (int i = 7; i >= 0; i--)
{
	bit = (X >> i) & 0x01;	// -> 00010001 & 0x01 -> 00000001
}
   
LED segments LOW - LED segment in on, HIGH - LED segment is off
0: 11000000
1: 11111001
   
algorithm: 
   
unsigned char segments[10] = {192, 249, ....};
unsigned char digits[3] = {1, 2, 4, 8};

we want to show 0 on the 2 position from the left

select 0 from segments -> A
select 1 from digits   -> B
   
setup of registers: most significan bit of B is connected to least significant bit of A 
A: | x | x | x | x | x | x | x | x |    B: | x | x | x | x | x | x | x | x | 
                                 ^           ^
                                  \---------/
latch = 0
loop for A:
7..0
	clock = 0               (8th bit in ODR)
   	bit = (A >> i) & 0x01;  (9th bit in ODR)
   	clock = 1
loop for B
7..0
	clock = 0
   	bit = (B >> i) & 0x01;  (9th bit in ODR)
   	clock = 1
latch = 1

1s precission stop watch
this display can only show one digit of four in one time (have no memory)

long T = 1;	// global
   
while(1)
{
	// update display without any delay
	display(T);
}
   
// systick interrupt
void systick_handle(void)
{
	T++;
}

#include "mam.h"
 
void gpio_init (void)
{
	// AHB1 - enable clock for GPIOA
	setbit(RCC->AHB1ENR, 0);
	// AHB1 - enable clock for GPIOB
	setbit(RCC->AHB1ENR, 1);
	// set mode of GPIOA5 to output
	setbit(GPIOA->MODER, 10);
	// set mode of GPIOA8 to output - clock
	setbit(GPIOA->MODER, 16);
	// set mode of GPIOA9 to output - data
	setbit(GPIOA->MODER, 18);
	// set mode of GPIOB5 to output - latch signal
	setbit(GPIOB->MODER, 10);
}
 
// delay function - doing literally nothing
void delay(unsigned long count) {
    while(count--);
}
 
void send_data (unsigned char data)
{
	for (int i = 7; i >= 0; i--)
	{
		// calculate value of a bit on i-th position
		unsigned char bit = (data >> i) & 0x01;
		if (bit == 1)
			setbit(GPIOA->ODR, 9);
		else
			clearbit(GPIOA->ODR, 9);
		// clock
		clearbit(GPIOA->ODR, 8);
		setbit(GPIOA->ODR, 8);
	}
}
 
static unsigned char number[10] = {192, 249, 164, 176, 153, 146, 130, 248, 128, 144};
static unsigned char position[] = {1, 2, 4, 8};
 
void set_digit (int a, int b)
{
	clearbit(GPIOB->ODR, 5);
	send_data (number[a]);
	send_data (position[b]);
	setbit(GPIOB->ODR, 5);
}
 
int main(void)
{
	gpio_init();
 
	while(1)
	{
		set_digit(1, 0);
		set_digit(2, 1);
		set_digit(3, 2);
		set_digit(4, 3);
	}
}

courses/be2m37mam/tasks/task02.txt · Last modified: 2021/11/04 15:57 by viteks