MAX7219 Simple interfacing problem

Go To Last Post
8 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello guys i'm trying to interface an ATMEGA32A  with a max7219 chip to drive 8 segment display,im using AS7 gcc ,my approach was to use any 3 port pins , one to shift data out from , one to use as a clock , and the last one for load pin required to latch data to the max7219 , however my code failed and i've been debugging for hours all i'm getting is blank 7 segment digits ,i've checked that my chip is working by connecting it to an arduino and used SPI library to display some digits and it seems to be working fine,when i tried adding delays with some leds and try to see what is happening i notice that my load pin never actually goes high, the clock pin never stop toggling even if it has already shifted out the 8 bits or so.

what i expect to happen : DIN pin starts shifting out data synchronized with the clk pin , after it is done sending ,clk should stop toggling and load pin goes high to latch the data but that never happens.

i've my code in 3 files , MAX7219.C , MAX7219.h and main.c

 

Main.c:

#define F_CPU 8000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <MAX7219.h>


int main(){
	
	MAX7219_init(); 
	MAX7219_send(TEST_REGISTER,YES_TEST);
	_delay_ms(2000);
	while(1){}
	}

 

MAX7219.C file:

/*
 
 * MAX7219 Driver.c
 
 *

 * Created: 8/2/2018 4:44:06 AM
 
 * Author : ~~~~~~~~~~~~~GARMOOOSHHHHHHHHHHH~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 */ 
#define F_CPU 8000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#define DIN 0
#define CLK 1
#define LOAD 2
#define MAX_PORT PORTA
#define MAX_DDR DDRA



/*set the pins as output */


void MAX7219_init(void){ 
	MAX_DDR=(1<<LOAD)|(1<<CLK)|(1<<DIN);                                //LOAD,CLK,DIN pins are outputs 
	MAX_PORT&=~((1<<LOAD)|(1<<CLK)|(1<<DIN));
}

/*transmits an 8 bit word by shifting through DIN  pin   , MSB  FIRST */

 void shift8bit(unsigned char data){
	uint8_t i;
	for(i=7;i>=0;i--){                                    
		if(data&(1<<i)){
			_delay_ms(1000);
			MAX_PORT|=(1<<DIN);
			_delay_ms(1000);                                //if THE BIT IS HIGH
			MAX_PORT|=(1<<CLK);
			_delay_ms(1000);
			MAX_PORT&=~(1<<CLK);
			_delay_ms(1000);
		}
		else{
			_delay_ms(1000);
			MAX_PORT&=~(1<<DIN);
			_delay_ms(1000);                               // ELSE THE BIT IS LOW 
			MAX_PORT|=(1<<CLK);
			_delay_ms(1000);
			MAX_PORT&=~(1<<CLK);
			_delay_ms(1000);
		}
	}
}


/*SENDS OUT A 16 BIT WORD , 8 BIT FOR ADDRESS , 8 BIT FOR DATA */

void MAX7219_send(unsigned char addr,unsigned char data){
	
shift8bit(addr);                                  //send out addr                             

shift8bit(data);                                 //send out data
_delay_ms(1000);
MAX_PORT|=(1<<LOAD);                             //rising edge on load pin
_delay_ms(1000);
MAX_PORT&=~(1<<LOAD);
_delay_ms(1000);                              //back to low
}


header file:

/*
 
 * MAX7219.h
 
 *
 
 * Created: 8/2/2018 4:44:48 AM
 
 *  Author: ~~~~~~~~~~~~~GARMOOOSHHHHHHHHHHH~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 */ 


#ifndef MAX7219_H_
#define MAX7219_H_



/*
*MAX 7219 REGISTER ADDRESSES 
*HIGH NIBBLE IS DONT CARE 
*REGISTER MAP OF MAX7219
******
*/

#define NOP_REGISTER 0X00
#define DIG0_REGISTER 0X01
#define DIG1_REGISTER 0X02
#define DIG2_REGISTER 0X03
#define DIG3_REGISTER 0X04
#define DIG4_REGISTER 0X05
#define DIG5_REGISTER 0X06
#define DIG6_REGISTER 0X07
#define DIG7_REGISTER 0X08
#define DECODE_REGISTER 0X09
#define INTENSITY_REGISTER 0X0A
#define SCAN_REGISTER 0X0B
#define SHUTDOWN_REGISTER 0X0C
#define TEST_REGISTER 0X0F

/* OP CODES FOR DIFFERENT REGISTERS 
*SHUT DOWN , NORMAL OPERATION ,INTENSITY CONTROL ETC
*
*/

#define DATA_MASK 0XF0
#define SHIFT_MASK 0X80
#define SHUTDOWN_MODE  0X00
#define NORMAL_MODE    0X01
#define YES_DECODEB    0XFF
#define NO_DECODEB 0X00
#define INTENSITY_LV0 0X00
#define INTENSITY_LV1 0X01
#define INTENSITY_LV2 0X02
#define INTENSITY_LV3 0X03
#define INTENSITY_LV4 0X04
#define INTENSITY_LV5 0X05
#define INTENSITY_LV6 0X06
#define INTENSITY_LV7 0X07
#define INTENSITY_LV8 0X08
#define INTENSITY_LV9 0X09
#define INTENSITY_LV10 0X0A
#define INTENSITY_LV11 0X0B
#define INTENSITY_LV12 0X0C
#define INTENSITY_LV13 0X0D
#define INTENSITY_LV14 0X0E
#define INTENSITY_LV15 0X0F
#define SCAN_1DIG 0X00
#define SCAN_2DIG 0X01
#define SCAN_3DIG 0X02
#define SCAN_4DIG 0X03
#define SCAN_5DIG 0X04
#define SCAN_6DIG 0X05
#define SCAN_7DIG 0X06
#define SCAN_8DIG 0X07
#define NO_TEST 0X00
#define YES_TEST 0X01






/*functions */




void MAX7219_init(void);

void MAX7219_send(unsigned char addr,unsigned char data);

void shift8bit(unsigned char data);









#endif /* MAX7219_H_ */

header file just contains register addresses and op codes copied from the datasheet.

i even used ready made code from other sites and used code given by kartman on other posts concerning max7219 but still my segments remain turned off, but works when i connect with my arduino.

any help is appreciated .

This topic has a solution.
Last Edited: Fri. Aug 3, 2018 - 10:12 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
	uint8_t i;
	for(i=7;i>=0;i--){                                    

What do you think this does?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

i think it loops from 7 to 0 so i can use ' i ' to test every bit of the argument data

come to think of it i have no idea what it will do in the last iteration with the uint8_t should i change it to char ? or am i completely wrong here?

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

garmoosh wrote:

i think it loops from 7 to 0 so i can use ' i ' to test every bit of the argument data

come to think of it i have no idea what it will do in the last iteration with the uint8_t should i change it to char ? or am i completely wrong here?

for a uint8_t, 0-1 = 255.  That's why your loop never ends, the tested condition never fails because an unsigned variable can never go below zero.

 

How to fix this depends on a few other matters, but yes, any signed variable type would solve the problem.

 

However, your (1<<i) is very inefficient on an AVR.  Better, IMO, to set a mask (mask = 0x80 if you're shifting out MSB first), test for each bit via (data & mask), and then shift mask right after each bit.  Then, as a side benefit, you don't even need to have a count variable, because when the mask is 1 and you shift right, it becomes 0, so you can just test for mask != 0 in your loop.

 

Another thing, please put some white space in your code.  The readability will improve immensely.

 

One final thing I noticed is that you have redundant code.  You repeat the clock output code in two places (1 data bit and 0 data bit), when it should only be in one place.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So something like this?

void shift8bit(unsigned char data){
	unsigned char mask=0x80;
	for(;mask;mask>>=1){                                   
		if(data&(mask)){
			MAX_PORT|=(1<<DIN);
		}
		else{
			MAX_PORT&=~(1<<DIN);}
			
				_delay_ms(1000);
				
				MAX_PORT|=(1<<CLK);
				
				_delay_ms(1000);
				
				MAX_PORT&=~(1<<CLK);
				
				_delay_ms(1000);
	}
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thanks for the help this worked , although when i changed the uint8_t to a char , it didn't work i have no idea why shouldn't changing to char would've also solved the problem?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Formatting is off, and still no whitespace, but that looks right.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

garmoosh wrote:
thanks for the help this worked , although when i changed the uint8_t to a char , it didn't work i have no idea why shouldn't changing to char would've also solved the problem?
In AVR GCC, char is equivalent to unsigned char.  You want signed char.  Or better yet, int8_t.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]