Menu

728x90

468x60

Navbar

Monday, October 5, 2026

A DIY SN74HC595 Dot-Matrix Display

 A dot matrix display is very popular among novice electronics students or hobbyists. They are widely available today with a very low cost. Using a dot matrix module with an Arduino is very common since they are very low cost and rich of resources.

A DIY SN74HC595 Dot-Matrix Display
Finished PCB Testing with an Arduino Uno


When I was a student a dot matrix module were expensive and it's difficult to find locally. So I bought some dot matrix displays, SN74HC595 and transistor driver to interface to a micro-controller. 

A DIY SN74HC595 Dot-Matrix Display
Finished Hand-made PCBA


A DIY SN74HC595 Dot-Matrix Display
Finished Hand-made PCBA

Making this dot matrix display by hands is very busy. I had to etch, clean, drill holes and assembly all parts on the PCB. It took a whole day to complete. 

For more details about this PCB please see this post. 

A DIY SN74HC595 8-digit and 10-digit Serial 7-Segment Display

The SN74HC595 is a popular standard logic shift registers chip. I has been used for driving dot matrix display, LEDs, relays etc. Driving a multi-digit serial seven-segment display is very convenience since the multiplexing method could not drive any display that's exceed 10 digits. However using a shift registers chip to drive the display yields a high brightness. 

A DIY SN74HC595 8-digit and 10-digit Serial 7-Segment Display
Arduino Testing

 

 

DIY SN74HC595 8-digit and 10-digit Serial 7-Segment Display
Finished PCB Assembly

 

If we have any individual-digit seven-segment display (any common anode or common cathode) we can put them together to make a serial display module manually. I have a dozen of the SN74HC595, common cathode seven-segment display, singled-sided copper clad board, passive components etc. So I want to make my own DIY display module. I have a Canon Laser printer with a good quality ink that can cover the circuit pattern well from acid penetration during etching. A toner-transfer method is suitable for this DIY single-sided PCB since the overall circuit is not complex. 

DIY SN74HC595 8-digit and 10-digit Serial 7-Segment Display
Copper Pattern Transferring to Copper Clad Board


I use the traditional Ferric Chloride acid etching yielded an acceptable quality with low cost. 

DIY SN74HC595 8-digit and 10-digit Serial 7-Segment Display
Finished PCB Etching and Drilling

Using a stand-drill with a machine-tool drill bit can easily drill all component pin holds of this FR-4 fiber glass PCB.

DIY SN74HC595 8-digit and 10-digit Serial 7-Segment Display
Digits Testing Using an Arduino Uno


We can control this serial display easily via an Arduino or a PIC microcontroller using their SPI interface. For more detail about this display see this post. 

 

 

 

 



 

Wednesday, February 25, 2026

ATMega644P SPI and 23K256 Serial SRAM

 Overview

The Microchip Technology Inc. 23X256 is a 256-Kbit Serial SRAM device. The memory is accessed via a simple Serial Peripheral Interface (SPI) compatible serial bus. The bus signals required are a clock input (SCK) plus separate data in (SI) and data out (SO) lines. Access to the device is controlled through a Chip Select (CS) input. Communication to the device can be paused via the hold pin (HOLD). While the device is paused, transitions on its inputs will be ignored, with the exception of Chip Select, allowing the host to service higher priority interrupts. 

ATMega644P SPI and 23K256 Serial SRAM

It supports clock rate up to 10MHz via its SPI interface. There many write and read modes, byte mode, page mode and sequential mode. Each pages contains 32 bytes of data.

ATMega644P SPI and 23K256 Serial SRAM 

This SPI chip does not have an address but it has some command before able read and write to this chip. Command or instruction locate at the first byte of data transmission. For example 0x03 for READ and 0x02 for WRITE.

ATMega644P SPI and 23K256 Serial SRAM
Data read and write using byte mode

 By default this device operates in byte read or write mode.

ATMega644P and 23K256 Interfacing

To get start the master ATMega644P MCU write and read data from this chip using byte mode. SRAM data will display on PORTC.

ATMega644P SPI and 23K256 Serial SRAM
Schematic

Source Code "main.c":

  1. /*
  2. * 12-spi_23K256.c
  3. *
  4. * Created: 2/25/2026 9:31:10 AM
  5. * Author : Admin
  6. */

  7. #include <avr/io.h>
  8. #include <util/delay.h>
  9. #define F_CPU 16000000UL

  10. #define DDR_SPI DDRB
  11. #define PRT_SPI PORTB

  12. #define DD_SS 4
  13. #define DD_MOSI 5
  14. #define DD_MISO 6
  15. #define DD_SCK 7

  16. void SPI_MasterInit(void)
  17. {
  18. /* Set MOSI and SCK output, all others input */
  19. DDR_SPI = (1<<DD_MOSI)|(1<<DD_SCK)|(1<<DD_SS);
  20. /* Enable SPI, Master, set clock rate fck/16 */
  21. SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
  22. }

  23. void SPI_MasterTransmit(char cData)
  24. {
  25. /* Start transmission */
  26. SPDR = cData;
  27. /* Wait for transmission complete */
  28. while(!(SPSR & (1<<SPIF)))
  29. ;
  30. }

  31. void SPI_SlaveInit(void)
  32. {
  33. /* Set MISO output, all others input */
  34. DDR_SPI = (1<<DD_MISO);
  35. /* Enable SPI */
  36. SPCR = (1<<SPE);
  37. }
  38. char SPI_SlaveReceive(void)
  39. {
  40. /* Wait for reception complete */
  41. while(!(SPSR & (1<<SPIF)))
  42. ;
  43. /* Return Data Register */
  44. return SPDR;
  45. }

  46. // 23K256 SPI SRAM

  47. void write_bytes_23K256(unsigned int address, unsigned char data){
  48. unsigned char temp;
  49. PRT_SPI&=~(1<<DD_SS);
  50. SPI_MasterTransmit(0x02);
  51. SPI_MasterTransmit(address>>8);
  52. SPI_MasterTransmit(address);
  53. SPI_MasterTransmit(data);
  54. PRT_SPI|=(1<<DD_SS);
  55. }

  56. unsigned char read_bytes_23K256(unsigned int address){
  57. PRT_SPI&=~(1<<DD_SS);
  58. SPI_MasterTransmit(0x03);
  59. SPI_MasterTransmit(address>>8);
  60. SPI_MasterTransmit(address);
  61. SPI_MasterTransmit(0xFF);
  62. unsigned char data=SPI_SlaveReceive();
  63. PRT_SPI|=(1<<DD_SS);
  64. return data;
  65. }
  66. int main(void)
  67. {
  68. /* Replace with your application code */
  69. SPI_MasterInit();
  70. PRT_SPI|=(1<<DD_SS);
  71. unsigned char temp=0, data[16];
  72. DDRC=0xFF;
  73. while (1)
  74. {
  75. for (unsigned int i=0;i<8;i++)
  76. {
  77. write_bytes_23K256(i,1<<i);
  78. PORTC=read_bytes_23K256(i);
  79. _delay_ms(1000);
  80. }
  81. }
  82. }







Now I put a character LCD to show data reading from the 23K256. This chip still operate in byte mode data read and write.

ATMega644P SPI and 23K256 Serial SRAM
Schematic

 Source Code "main.c":

  1. /*
  2. * 23K256_1602.c
  3. *
  4. * Created: 2/25/2026 10:50:02 AM
  5. * Author : Admin
  6. */

  7. #include <avr/io.h>
  8. #include <util/delay.h>
  9. #define F_CPU 16000000UL

  10. #define DDR_SPI DDRB
  11. #define PRT_SPI PORTB

  12. #define DD_SS 4
  13. #define DD_MOSI 5
  14. #define DD_MISO 6
  15. #define DD_SCK 7

  16. void delay_1(unsigned int value){
  17. for (unsigned int i=0;i<value;i++)
  18. {
  19. }
  20. }
  21. void SPI_MasterInit(void)
  22. {
  23. /* Set MOSI and SCK output, all others input */
  24. DDR_SPI = (1<<DD_MOSI)|(1<<DD_SCK)|(1<<DD_SS);
  25. /* Enable SPI, Master, set clock rate fck/16 */
  26. SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
  27. }

  28. void SPI_MasterTransmit(char cData)
  29. {
  30. /* Start transmission */
  31. SPDR = cData;
  32. /* Wait for transmission complete */
  33. while(!(SPSR & (1<<SPIF)))
  34. ;
  35. }

  36. void SPI_SlaveInit(void)
  37. {
  38. /* Set MISO output, all others input */
  39. DDR_SPI = (1<<DD_MISO);
  40. /* Enable SPI */
  41. SPCR = (1<<SPE);
  42. }
  43. char SPI_SlaveReceive(void)
  44. {
  45. /* Wait for reception complete */
  46. while(!(SPSR & (1<<SPIF)))
  47. ;
  48. /* Return Data Register */
  49. return SPDR;
  50. }

  51. // 23K256 SPI SRAM

  52. void write_bytes_23K256(unsigned int address, unsigned char data){
  53. unsigned char temp;
  54. PRT_SPI&=~(1<<DD_SS);
  55. SPI_MasterTransmit(0x02);
  56. SPI_MasterTransmit(address>>8);
  57. SPI_MasterTransmit(address);
  58. SPI_MasterTransmit(data);
  59. PRT_SPI|=(1<<DD_SS);
  60. //delay_1(1000);
  61. }

  62. unsigned char read_bytes_23K256(unsigned int address){
  63. PRT_SPI&=~(1<<DD_SS);
  64. SPI_MasterTransmit(0x03);
  65. SPI_MasterTransmit(address>>8);
  66. SPI_MasterTransmit(address);
  67. SPI_MasterTransmit(0xFF);
  68. //delay_1(1000);
  69. unsigned char data=SPI_SlaveReceive();
  70. PRT_SPI|=(1<<DD_SS);
  71. return data;
  72. }
  73. int main(void)
  74. {
  75. /* Replace with your application code */
  76. _delay_ms(50);
  77. SPI_MasterInit();
  78. PRT_SPI|=(1<<DD_SS);
  79. unsigned char temp=0, data[16];
  80. lcd_init();
  81. lcd_clear();
  82. lcd_text("ATMega644P SRAM");
  83. lcd_xy(1,2);
  84. lcd_text("Serial 23K256");
  85. _delay_ms(10000);
  86. lcd_clear();
  87. for (unsigned int i=0;i<10;i++)
  88. {
  89. write_bytes_23K256(i,'0'+i);
  90. }
  91. for (unsigned int i=0;i<10;i++)
  92. {
  93. lcd_data(read_bytes_23K256(i));
  94. }
  95. lcd_xy(1,2);
  96. for (unsigned int i=0;i<16;i++)
  97. {
  98. write_bytes_23K256(i+10,'A'+i);
  99. }
  100. for (unsigned int i=0;i<16;i++)
  101. {
  102. lcd_data(read_bytes_23K256(i+10));
  103. }
  104. while (1)
  105. {
  106. }
  107. }


The LCD drivers are not here you can download this project package in download section below. I tested it on my AVR ATMega644P prototype board. It works fine and fast. But the wires connection problem between the prototype board and the bread board often cause problems to data communication.

ATMega644P SPI and 23K256 Serial SRAM 


ATMega644P SPI and 23K256 Serial SRAM


Using sequential writing and reading mode could save processing time. However the master MCU must put the 23K256 to operate in this mode by writing an instruction to this chip.

ATMega644P SPI and 23K256 Serial SRAM
Read Status Register Instruction

 The schematic is shown in previous example. The LCD shows the result of data reading from SRAM.

Source Code "main.c":

  1. /*
  2. * 23K256_Sequential_1602.c
  3. *
  4. * Created: 2/25/2026 2:37:30 PM
  5. * Author : Admin
  6. */

  7. #include <avr/io.h>
  8. #include <util/delay.h>
  9. #define F_CPU 16000000UL
  10. #include <stdio.h>

  11. #define DDR_SPI DDRB
  12. #define PRT_SPI PORTB

  13. #define DD_SS 4
  14. #define DD_MOSI 5
  15. #define DD_MISO 6
  16. #define DD_SCK 7

  17. void delay_1(unsigned int value){
  18. for (unsigned int i=0;i<value;i++)
  19. {
  20. }
  21. }
  22. void SPI_MasterInit(void)
  23. {
  24. /* Set MOSI and SCK output, all others input */
  25. DDR_SPI = (1<<DD_MOSI)|(1<<DD_SCK)|(1<<DD_SS);
  26. /* Enable SPI, Master, set clock rate fck/16 */
  27. SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
  28. }

  29. void SPI_MasterTransmit(char cData)
  30. {
  31. /* Start transmission */
  32. SPDR = cData;
  33. /* Wait for transmission complete */
  34. while(!(SPSR & (1<<SPIF)))
  35. ;
  36. }

  37. void SPI_SlaveInit(void)
  38. {
  39. /* Set MISO output, all others input */
  40. DDR_SPI = (1<<DD_MISO);
  41. /* Enable SPI */
  42. SPCR = (1<<SPE);
  43. }
  44. char SPI_SlaveReceive(void)
  45. {
  46. /* Wait for reception complete */
  47. while(!(SPSR & (1<<SPIF)))
  48. ;
  49. /* Return Data Register */
  50. return SPDR;
  51. }

  52. // 23K256 SPI SRAM

  53. void write_bytes_23K256(unsigned int address, unsigned char data){
  54. unsigned char temp;
  55. PRT_SPI&=~(1<<DD_SS);
  56. SPI_MasterTransmit(0x02);
  57. SPI_MasterTransmit(address>>8);
  58. SPI_MasterTransmit(address);
  59. SPI_MasterTransmit(data);
  60. PRT_SPI|=(1<<DD_SS);
  61. }

  62. unsigned char read_bytes_23K256(unsigned int address){
  63. PRT_SPI&=~(1<<DD_SS);
  64. SPI_MasterTransmit(0x03);
  65. SPI_MasterTransmit(address>>8);
  66. SPI_MasterTransmit(address);
  67. SPI_MasterTransmit(0xFF);
  68. unsigned char data=SPI_SlaveReceive();
  69. PRT_SPI|=(1<<DD_SS);
  70. return data;
  71. }

  72. void write_sequential_23K256(unsigned int address, unsigned char *data){
  73. PRT_SPI&=~(1<<DD_SS);
  74. SPI_MasterTransmit(0x01);
  75. SPI_MasterTransmit(1<<6);
  76. PRT_SPI|=(1<<DD_SS);
  77. unsigned char temp;
  78. PRT_SPI&=~(1<<DD_SS);
  79. SPI_MasterTransmit(0x02);
  80. SPI_MasterTransmit(address>>8);
  81. SPI_MasterTransmit(address);
  82. while(*data) { SPI_MasterTransmit(*data++); delay_1(10);}
  83. PRT_SPI|=(1<<DD_SS);
  84. }

  85. unsigned char data_read[32];
  86. void read_sequential_23K256(unsigned int address,unsigned int size){
  87. PRT_SPI&=~(1<<DD_SS);
  88. SPI_MasterTransmit(0x01);
  89. SPI_MasterTransmit(1<<6);
  90. PRT_SPI|=(1<<DD_SS);
  91. unsigned char *temp;
  92. PRT_SPI&=~(1<<DD_SS);
  93. SPI_MasterTransmit(0x03);
  94. SPI_MasterTransmit(address>>8);
  95. SPI_MasterTransmit(address);
  96. for (unsigned int i=0;i<size;i++)
  97. {
  98. SPI_MasterTransmit(0xFF);
  99. data_read[i]=SPI_SlaveReceive();
  100. delay_1(10);
  101. }
  102. PRT_SPI|=(1<<DD_SS);
  103. }

  104. int main(void)
  105. {
  106. /* Replace with your application code */
  107. _delay_ms(500);
  108. SPI_MasterInit();
  109. PRT_SPI|=(1<<DD_SS);

  110. lcd_init();
  111. lcd_clear();
  112. while (1)
  113. {
  114. lcd_xy(1,1);
  115. write_sequential_23K256(0,"ATMEGA644P SPI");
  116. for (unsigned int i=0;i<14;i++)
  117. {
  118. data_read[i]=read_bytes_23K256(i);
  119. }
  120. lcd_text(data_read);
  121. write_sequential_23K256(16,"23K256 SRAM ");
  122. lcd_xy(1,2);
  123. read_sequential_23K256(16,16);
  124. lcd_text(data_read);
  125. _delay_ms(10000);
  126. lcd_clear();
  127. write_sequential_23K256(32,"ABCDEFGHIJKLMOPQ");
  128. lcd_xy(1,1);
  129. read_sequential_23K256(32,16);
  130. lcd_text(data_read);
  131. write_sequential_23K256(64,"RSTUVWXYZ !@#$%^");
  132. lcd_xy(1,2);
  133. read_sequential_23K256(64,16);
  134. lcd_text(data_read);
  135. _delay_ms(10000);
  136. lcd_clear();
  137. }
  138. }

I tested it on AVR ATMega644P Prototype Board. There are some unwanted data on SRAM space. So the master MCU must clear them first.

ATMega644P SPI and 23K256 Serial SRAM 


ATMega644P SPI and 23K256 Serial SRAM


Click here to download this example.



 

 

 

 

336x280

Search This Blog

Labels

23K256 (1) 24C16B (2) 25AA010A (2) 8051 (7) 93AA46B (1) ADC (34) Analog Comparator (1) Arduino (16) ARM (13) AT89C52 (7) ATMega32 (58) ATMega644P (27) AVR (87) AVR PCB (2) Bootloader (1) CCS PICC (31) Change Notify Interrupt (CNI) (2) DAC (2) DHT11 (4) Display (135) Distance Sensor (3) dot matrix (1) ds1307 (10) DS18B20 (5) ds3231 (1) ds3232 (2) dsPIC (5) dsPIC30F1010 (3) dsPIC30F2010 (5) EEPROM (5) Environment Sensor (5) ESP32 (1) esp8266 (1) Graphical LCD (2) I2C (38) ILI9341 (1) Input/Output (76) Interrupt (22) IoT PCB (1) Keil (5) Keypad (16) KS0108 (2) LCD (75) LM35 (3) Master/Slave (2) MAX7221 (1) MCP23017 (8) MCP23S17 (7) MCP4921 (1) MCP4922 (2) Meter (3) MikroC (2) Module PCB (1) Motor (15) MPLABX (73) Nokia 5110 LCD (4) OLED (2) One-Wire (7) Oscillator (8) PCB (12) PCD8544 (3) PCF8574 (10) PIC (108) PIC12F (3) PIC16 (105) PIC16F628A (3) PIC16F630 (2) PIC16F716 (4) PIC16F818 (11) PIC16F818/819 (3) PIC16F84A (16) PIC16F876A (2) PIC16F877A (9) PIC16F88 (2) PIC16F887 (60) PIC18 (19) PIC18F1220 (5) PIC18F2550 (5) PIC18F4550 (12) PICKit2 (1) PICMicro PCB (4) Pin Change Interrupt (1) PWM (12) RTC (12) SBN0064G (1) Sensor (13) SH1106 (3) Shift Register (13) Shift Registers (12) SN74HC595N (2) Software TWI (2) SPI (39) ST7735 (1) STM32 (11) STM32 Black Pill (1) STM32 Blue Pill (12) STM32 HAL (5) STM32CubeIDE (13) STM32F103C8T6 (9) STM32F401CCU6 (1) SysTick (4) temperature sensor (13) TFT (1) TG12864A (1) Thermometer (22) Timer/Counter (32) TM1637 (2) twi (10) UART (8) Ultrasonic (4) Voltmeter (7) WDT (1) XC16 (2) XC8 (96)