Continue to Site

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.

led matrix with MCS-51 and CD4094

Status
Not open for further replies.

Asok Sankar Rudra

Newbie level 6
Joined
Aug 15, 2005
Messages
11
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,415
cd4094

Dear Freinds,
This is my first post,still not sure about all the RULES.Kindly bear with me.
I attach to propose as my project md4094_24C_.gif.
Hope the message is conveyed.Please let me know.
This is a modified version of a commercial product.
Now can I have assistance in developing multiplexing/scrolling/animation code.preferably with MCS-51? Internet,which has taught me(Read:given me code)
multiplexing scrolling with 74LS164, is almost silent about my current problem.Even then here is my undestanding on CD4094B:
1)from data sheet:-"The CD4094BC consists of an 8-bit shift register and a 3-STATE 8-bit latch. Data is shifted serially through the shift register on the positive transition of the clock. ....These gates are enabled when OUTPUT ENABLE is taken HIGH."
2)from expert e:A latch is not a flip flop, when the gate is open (in your case STROBE is high) data flow freely from the input to the output, when the gate is closed (in your case STROBE is low)there is no connection. Thus data is latched whenever the gate is closed. Thus the time data is latched is when the gate closes (in your case "on the negative edge of the STROBE") and it will stay the same till the gate is opened.
3)from professor K:So to keep the STROBE input logic low during shift operations. When all the shifting is done, means after stopping any activity at CLOCK input, then pulse the STROBE input high for a short period: The low to high toggle will make the latch becoming "transparent", means the output will show a copy of stored data in shift register. The high to low toggle, just afterwards, will keep the actualized outputs latched. So, the outputs become actualized with the low to high edge at STROBE input.
4) HSETI.htm of Airborn;please google.
5)https://www.allaboutcircuits.com/vol_4/chpt_12/4.html.
But there is no reference of what will happen if CLK and STROBE pins are shorted and used together;see md4094_24C_.gif.How to clear all outputs of 4094 at the outset to ensure screen blanking? Then what?
Has anybody exact experience which he wants to share?
Another GREAT ISSUE is choice of multiplexing mode :rows or columns?
With best regards
A.S.Rudra
 

cd4094 schematic

well i made a led matrix studying many posts from this forum try 'search' u will get many specially this one

but i got the scrolling idea from this code

Code:
#include <90s8535.h>
#include <delay.h>                  
                              

// led display
#define LED_RESET		PORTB.0
#define LED_CLOCK		PORTB.1
#define LED_DATA		PORTB.4	
#define SCROLL_DELAY	140  // multiple of 7 (use smaller numbers for faster scroll)

// keyboard 
#define KBD_CLOCK		PORTD.2  // to be used for host -> keyboard communication
#define KBD_DATA        	PIND.4                                 
#define BUFF_SIZE		64
            
// lcd 
#define LCD_RS			PORTD.5
#define LCD_RW 		PORTD.6
#define LCD_E  		PORTD.7 	 
#define COMMAND_MODE 	0
#define DATA_MODE    	1	     
#define WRITE_MODE   	0
#define READ_MODE    	1 		                                                              
#define LCD_DATA_PORT	PORTC     
                  
// functions                  
void lcd_init(void);
void lcd_clear(void);
void lcd_putc(unsigned char);
void lcd_putsf(unsigned char flash *); 
void lcd_puts(unsigned char *str);
interrupt [EXT_INT0] keyboard_isr(void); 
void put_char_kbbuff(unsigned char);   
void put_scancode_kbbuff(unsigned char);
int getchar(void);                  
int kbhit(void);
void decode(unsigned char);

// global variables ***************************    
unsigned char kb_buffer[BUFF_SIZE];
unsigned char bitcount;	    
unsigned char *inpt, *outpt;
unsigned char buffcnt = 0;                                                                                                                    

// led character definitions 
// 5 data columns + 1 space
// for each character
flash unsigned char led_chars[94][6] = {  
0x00,0x00,0x00,0x00,0x00,0x00,	// space
0x00,0x00,0xfa,0x00,0x00,0x00,	// !	
0x00,0xe0,0x00,0xe0,0x00,0x00,	// "
0x28,0xfe,0x28,0xfe,0x28,0x00,	// #
0x24,0x54,0xfe,0x54,0x48,0x00,  // $
0xc4,0xc8,0x10,0x26,0x46,0x00,  // %
0x6c,0x92,0xaa,0x44,0x0a,0x00,  // &
0x00,0xa0,0xc0,0x00,0x00,0x00,  // '
0x00,0x38,0x44,0x82,0x00,0x00,	// (
0x00,0x82,0x44,0x38,0x00,0x00,  // )
0x28,0x10,0x7c,0x10,0x28,0x00,  // *
0x10,0x10,0x7c,0x10,0x10,0x00,  // +
0x00,0x0a,0x0c,0x00,0x00,0x00,  // ,
0x10,0x10,0x10,0x10,0x10,0x00,  // -
0x00,0x06,0x06,0x00,0x00,0x00,  // .
0x04,0x08,0x10,0x20,0x40,0x00,  // /  
0x7c,0x8a,0x92,0xa2,0x7c,0x00,  // 0
0x00,0x42,0xfe,0x02,0x00,0x00,  // 1
0x42,0x86,0x8a,0x92,0x62,0x00,  // 2
0x84,0x82,0xa2,0xd2,0x8c,0x00,	// 3
0x18,0x28,0x48,0xfe,0x08,0x00,	// 4
0xe5,0xa2,0xa2,0xa2,0x9c,0x00,	// 5
0x3c,0x52,0x92,0x92,0x0c,0x00,	// 6
0x80,0x8e,0x90,0xa0,0xc0,0x00,	// 7
0x6c,0x92,0x92,0x92,0x6c,0x00,	// 8
0x60,0x92,0x92,0x94,0x78,0x00,	// 9  
0x00,0x6c,0x6c,0x00,0x00,0x00,	// :
0x00,0x6a,0x6c,0x00,0x00,0x00,	// ;
0x10,0x28,0x44,0x82,0x00,0x00,	// <
0x28,0x28,0x28,0x28,0x28,0x00,	// =
0x00,0x82,0x44,0x28,0x10,0x00,	// >
0x40,0x80,0x8a,0x90,0x60,0x00,	// ?
0x4c,0x92,0x9e,0x82,0x7c,0x00,	// @
0x7e,0x88,0x88,0x88,0x7e,0x00,	// A
0xfe,0x92,0x92,0x92,0x6c,0x00,	// B
0x7c,0x82,0x82,0x82,0x44,0x00,	// C
0xfe,0x82,0x82,0x44,0x38,0x00,	// D
0xfe,0x92,0x92,0x92,0x82,0x00,	// E
0xfe,0x90,0x90,0x90,0x80,0x00,	// F
0x7c,0x82,0x92,0x92,0x5e,0x00,	// G
0xfe,0x10,0x10,0x10,0xfe,0x00,	// H
0x00,0x82,0xfe,0x82,0x00,0x00,	// I
0x04,0x02,0x82,0xfc,0x80,0x00,	// J
0xfe,0x10,0x28,0x44,0x82,0x00,	// K
0xfe,0x02,0x02,0x02,0x02,0x00,	// L
0xfe,0x40,0x30,0x40,0xfe,0x00,	// M
0xfe,0x20,0x10,0x08,0xfe,0x00,	// N
0x7c,0x82,0x82,0x82,0x7c,0x00,	// O
0xfe,0x90,0x90,0x90,0x60,0x00,	// P
0x7c,0x82,0x8a,0x84,0x7a,0x00,	// Q
0xfe,0x90,0x98,0x94,0x62,0x00,	// R
0x62,0x92,0x92,0x92,0x8c,0x00,	// S
0x80,0x80,0xfe,0x80,0x80,0x00,	// T
0xfc,0x02,0x02,0x02,0xfc,0x00,	// U
0xf8,0x04,0x02,0x04,0xf8,0x00,	// V
0xfc,0x02,0x1c,0x02,0xfc,0x00,	// W
0xc6,0x28,0x10,0x28,0xc6,0x00,	// X
0xe0,0x10,0x0e,0x10,0xe0,0x00,	// Y
0x86,0x8b,0x92,0xa2,0xc2,0x00,	// Z
0x00,0xfe,0x82,0x82,0x00,0x00,	// [
0x00,0x00,0x00,0x00,0x00,0x00,     // *** do not remove this empty char ***
0x00,0x82,0x82,0xfe,0x00,0x00,	// ]
0x20,0x40,0x80,0x40,0x20,0x00,	// ^
0x02,0x02,0x02,0x02,0x02,0x00,	// _
0x00,0x80,0x40,0x20,0x00,0x00,	// `
0x04,0x2a,0x2a,0x2a,0x1e,0x00,	// a
0xfe,0x12,0x22,0x22,0x1c,0x00,	// b
0x1c,0x22,0x22,0x22,0x04,0x00,	// c
0x1c,0x22,0x22,0x12,0xfe,0x00,	// d
0x1c,0x2a,0x2a,0x2a,0x18,0x00,	// e
0x10,0x7e,0x90,0x80,0x40,0x00,	// f
0x30,0x4a,0x4a,0x4a,0x7c,0x00,	// g
0xfe,0x10,0x20,0x20,0x1e,0x00,	// h
0x00,0x22,0xbe,0x02,0x00,0x00,	// i
0x04,0x02,0x22,0xbc,0x00,0x00,	// j
0xfe,0x08,0x14,0x22,0x00,0x00,	// k
0x00,0x82,0xfe,0x02,0x00,0x00,	// l
0x3e,0x20,0x18,0x20,0x1e,0x00,	// m
0x3e,0x10,0x20,0x20,0x1e,0x00,	// n
0x1c,0x22,0x22,0x22,0x1c,0x00,	// o
0x3e,0x28,0x28,0x28,0x10,0x00,	// p
0x10,0x28,0x28,0x18,0x3e,0x00,	// q
0x3e,0x10,0x20,0x20,0x10,0x00,	// r
0x12,0x2a,0x2a,0x2a,0x04,0x00,	// s
0x20,0xfc,0x22,0x02,0x04,0x00,	// t
0x3c,0x02,0x02,0x04,0x3e,0x00,	// u
0x38,0x04,0x02,0x04,0x38,0x00,	// v
0x3c,0x02,0x0c,0x02,0x3c,0x00,	// w
0x22,0x14,0x08,0x14,0x22,0x00,	// x
0x30,0x0a,0x0a,0x0a,0x3c,0x00,	// y
0x22,0x26,0x2a,0x32,0x22,0x00, 	// z
0x00,0x10,0x6c,0x82,0x00,0x00,	// { 
0x00,0x00,0xfe,0x00,0x00,0x00,	// |
0x00,0x82,0x6c,0x10,0x00,0x00 };	// }


// keyboard scan codes (without & with shift key pressed)
flash unsigned char unshifted[67][2] = {
//0x0d,9,
0x0e,'`',0x15,'q',0x16,'1',0x1a,'z',0x1b,'s',0x1c,'a',0x1d,'w',0x1e,'2',0x21,'c',0x22,'x',0x23,'d',0x24,'e',
0x25,'4',0x26,'3',0x29,' ',0x2a,'v',0x2b,'f',0x2c,'t',0x2d,'r',0x2e,'5',0x31,'n',0x32,'b',0x33,'h',0x34,'g',
0x35,'y',0x36,'6',0x39,',',0x3a,'m',0x3b,'j',0x3c,'u',0x3d,'7',0x3e,'8',0x41,',',0x42,'k',0x43,'i',0x44,'o',
0x45,'0',0x46,'9',0x49,'.',0x4a,'/',0x4b,'l',0x4c,';',0x4d,'p',0x4e,'-',0x52,'`',0x54,'[',0x55,'=',0x5a,13,
0x5b,']',0x5d,'/',0x61,'<',0x66,8,  0x69,'1',0x6b,'4',0x6c,'7',0x70,'0',0x71,',',0x72,'2',0x73,'5',0x74,'6',
0x75,'8',0x79,'+',0x7a,'3',0x7b,'-',0x7c,'*',0x7d,'9',0,0 };


flash unsigned char shifted[67][2] = {
//0x0d,9,
0x0e,'`',0x15,'Q',0x16,'!',0x1a,'Z',0x1b,'S',0x1c,'A',0x1d,'W',0x1e,'@',0x21,'C',0x22,'X',0x23,'D',0x24,'E',
0x25,'$',0x26,'#',0x29,' ',0x2a,'V',0x2b,'F',0x2c,'T',0x2d,'R',0x2e,'%',0x31,'N',0x32,'B',0x33,'H',0x34,'G',
0x35,'Y',0x36,'^',0x39,'L',0x3a,'M',0x3b,'J',0x3c,'U',0x3d,'&',0x3e,'*',0x41,'<',0x42,'K',0x43,'I',0x44,'O',
0x45,')',0x46,'(',0x49,'>',0x4a,'?',0x4b,'L',0x4c,':',0x4d,'P',0x4e,'_',0x52,'"',0x54,'{',0x55,'+',0x5a,13,
0x5b,'}',0x5d,'|',0x61,'>',0x66,8,  0x69,'1',0x6b,'4',0x6c,'7',0x70,'0',0x71,',',0x72,'2',0x73,'5',0x74,'6',
0x75,'8',0x79,'+',0x7a,'3',0x7b,'-',0x7c,'*',0x7d,'9',0,0 };
                       



//***********************************************
void main() {                                               	
	int i,j;
    	unsigned char ch,row;
	flash unsigned char *dataPtr, *tmpDataPtr;
	unsigned char messageLength, currentChar, charOffset, tmpCurrentChar, tmpCharOffset, ledArray[23];	
	unsigned char message[308];  // 300 chars + 4 spaces at start and end of message                   
	
	#asm("cli");    // disable all interrupts 
	// initialise ports 
	DDRA = 0xff;	// port A output 	
	DDRB = 0xff;	// port B output	
	DDRC = 0xff;	// port C output	
	DDRD = 0xeb;	// pins 2 & 4 inputs    
	
	// initialise keyboard variables
	inpt = kb_buffer; 
	outpt = kb_buffer;
	buffcnt = 0;
	bitcount = 11;
	
	// initialise lcd 
	lcd_init();       	    	            
	                                                 
	// initialise LED display (shift registers)	
	LED_RESET = 0;
   	LED_CLOCK = 0;
 	LED_RESET = 1;                  
	                  
	// initialise interrupt registers
	GIMSK = 0x40;	// enable INT0 interrupt
	MCUCR = 0x02;	// INT0 interrupt on falling edge    
	
	
   	#asm("sei");    // enable all interrupts
   	    
   	      
   	while(1) {
   		ch = 0x00;
    		i = 0;
    		// fill the array with 4 empty spaces at the start and the end of the message
		// as the screen has 4 chars
		// (it looks better if we start scrolling with empty screen and end
		// with empty screen , rather than displaying four chars immediatelly and
		// then start scrolling)
		message[i++] = ' ';   
   		message[i++] = ' ';   
   		message[i++] = ' ';   
   		message[i++] = ' ';    

		// enter message until 300 characters entered or <enter> key pressed  	        
    		while((ch != 13) || (i < 308)) {      
			ch = getchar();
			if ((ch != 13) && (ch != 'q')) {
				lcd_putc(ch);
				message[i++] = ch;
			}
			// if q is pressed clear the LCD 
			// (code only writes to the first LCD line so
			// if the line is longer than 16 chars i cant see the rest of the chars
			// , there will be a menu system in the future software version
			// and the line on the LCD will be scrolled 
			// to the left automatically as the cursor gets to the end of the line
			//, for now use this dirty solution:))
			if (ch == 'q') 
				lcd_clear();	            			
		}              
    		message[i++] = ' ';   
   		message[i++] = ' ';   
   		message[i++] = ' ';   
   		message[i++] = ' ';    	   	   	    
    
    		messageLength = i - 4;
    		charOffset = 0;
    		currentChar = 0;
    		dataPtr = &led_chars[message[0] - 0x20][0];    
    		
		// this loop is the heart of the scroll
		// message is scrolled until a key is hit on the keyboard		

    		while (!kbhit()) {     
    			// load led array   	
    			tmpDataPtr = dataPtr;
    			tmpCharOffset = charOffset;
    			tmpCurrentChar = currentChar;
    			for (i = 0; i <= 22; i++) {  
    				ledArray[i] = *tmpDataPtr++;  		    	   		    		
    	 			if (++tmpCharOffset==0x06) {  
    	  				tmpCharOffset = 0;    	  		    	  		
    					if (++tmpCurrentChar == messageLength)
    	 					tmpCurrentChar = 0; 
    	  				tmpDataPtr = &led_chars[message[tmpCurrentChar] - 0x20][0];
    				}      		
    			}
    			if (++charOffset == 0x06) {     
    				charOffset = 0;         		
    				if (++currentChar == messageLength)
    					currentChar = 0;	
    			}      
    			dataPtr = &led_chars[message[currentChar] - 0x20][charOffset];
    	    	
    			// display led array
    			row = 0x02;        
    			for (j = 0;j <= SCROLL_DELAY; j++) {  
	   			for (i = 0; i <= 22; i++) {
    					LED_DATA = (ledArray[i] & row) ? 1 : 0;
    					LED_CLOCK = 1;
    					LED_CLOCK = 0;    	
    				}                 
    				PORTA = row;  
 				row <<= 1;      // next line to be switched on         
 				if (!row) 	// if last line go back to the first line	
 					row = 0x02; 	  	 	  
 	  			delay_us(800);
 	    			PORTA = 0x00; 	    
 	   		}
    		}
		lcd_clear();	    
    }
    
        	       
} 

//***********************************************
// return 1 if a key is pressed (non blocking)
// else return 0 
int kbhit(void) {
	if (buffcnt) {
		// reset buffer variables (flush the buffer)
		inpt = kb_buffer; 
		outpt = kb_buffer;
		buffcnt = 0;
		bitcount = 11;
		return 1;		
	}
    return 0;
}

// puts scan code (in hex format) into keyboard buffer
// (used for debugging purposes)  
//***********************************************
void put_scancode_kbbuff(unsigned char sc) {
	unsigned char h,l;

	// convert hi and low nibbles of the scancode
	// into ascii and store them into keyboard buffer	
	h =  ((sc & 0xf0 ) >> 0x04) & 0x0f;
	if ( h > 9)
		h = h + 7;
	h = h + 0x30;
	put_char_kbbuff(h);             
	
	l = sc & 0x0f;
	if ( l > 9)
		l = l + 7;
	l = l + 0x30;
	put_char_kbbuff(l);
}       
//***********************************************
// keyboard ISR  
interrupt [EXT_INT0] keyboard_isr(void) { 
	static unsigned char data;	// holds the received scan code

	// function entered at falling edge of the kbd clock signal 
	// if data bit is the next bit to be read 
	// (bit 3 to 10 is data, start, stop & parity bis are ignored
	if((bitcount < 11) && (bitcount > 2)) {		
		data = (data >> 1);      
		if (KBD_DATA)			// if next bit is 1	 
			data = data | 0x80;	// store a '1'
		else 
			data = data & 0x7f; // else store a '0'
	}		
	if(--bitcount == 0) {		// all bits received ?		
		   	decode(data);       // decode received byte
			bitcount = 11;		// reset bit counter						
	}  
}               
//***********************************************
// decode scan code
void decode(unsigned char sc) {
 	static unsigned char is_up=0, shift = 0, mode = 0;
	unsigned char i;
 
	if (!is_up) {
		switch (sc) {
			case 0xF0 :// The up-key identifier
				is_up = 1;
				break;
			case 0x12 :// Left SHIFT
				shift = 1;
				break;
			case 0x59 :// Right SHIFT
				shift = 1;
				break;
			case 0x05 :// F1
				if(mode == 0)
					mode = 1;// Enter scan code mode
				if(mode == 2)
					mode = 3;// Leave scan code mode
				break;
			default:
				if(mode == 0 || mode == 3) {// If ASCII mode				
					if(!shift) {// If shift not pressed, do a table look-up
						for(i = 0; unshifted[i][0]!=sc && unshifted[i][0]; i++);
							if (unshifted[i][0] == sc) {
								put_char_kbbuff(unshifted[i][1]);							
							}													
					} 
					else {// If shift pressed
						for(i = 0; shifted[i][0]!=sc && shifted[i][0]; i++);
							if (shifted[i][0] == sc) {
								put_char_kbbuff(shifted[i][1]);
							}
					}
				} 
				else put_scancode_kbbuff(sc);	// scan code mode (debugging mode)								
				break;
		}
	} 
	else {
		is_up = 0;// Two 0xF0 in a row not allowed
		switch (sc) {
			case 0x12 :// Left SHIFT
				shift = 0;
				break;
			case 0x59 :// Right SHIFT
				shift = 0;
				break;
			case 0x05 :// F1 --  F1 puts you in debugging mode
				   // pressing F1 again gets you out of debugging mode
				   // in debugging mode hex code of the scan codes
				   // are stored in the buffer instead of their ascii codes		
				if(mode == 1)
				mode = 2;
				if(mode == 3)
					mode = 0;
				break;		
		}
	}
}                                                
//***********************************************
// store character in the keyboard ring buffer 
void put_char_kbbuff(unsigned char c) {
	if (buffcnt < BUFF_SIZE) { // if buffer is not full
		*(inpt++) = c;
		buffcnt++;
		if (inpt >= kb_buffer + BUFF_SIZE) // pointer wrapping
			inpt = kb_buffer;
	}		
} 
   
//***********************************************
// get next available character from the keyboard ring buffer
// (waits until a character is available in the buffer)
int getchar(void) {
	int byte;
	
	while (buffcnt == 0); // wait for data
	byte = *outpt; // get byte
	outpt++;
	if (outpt >= kb_buffer + BUFF_SIZE) // pointer wrapping
		outpt = kb_buffer;
	buffcnt--; // decrement buffer count
	return byte;
}
//***********************************************
void lcd_init(void) {
	delay_ms(50);
	LCD_E = 0;
	LCD_RS = COMMAND_MODE;	
	LCD_RW = WRITE_MODE;		
	delay_ms(1);
	LCD_DATA_PORT = 0x38;	// 8 bit, 2 lines, 5x8 font
	LCD_E = 1;	delay_ms(1);
	LCD_E = 0;	delay_ms(1);
	LCD_DATA_PORT = 0x0f;	// display & cursor ON, blink & underlined 
	LCD_E = 1;	delay_ms(1);
	LCD_E = 0;	delay_ms(2);
	lcd_clear();				 	
}                                         
//***********************************************
void lcd_clear(void) {  
	LCD_RS = COMMAND_MODE;
    LCD_DATA_PORT = 0x01;	// clear display
	LCD_E = 1;	delay_ms(1);
	LCD_E = 0;	delay_ms(2);
}                               
//***********************************************
// display char on lcd
void lcd_putc(unsigned char ch) {
	LCD_RS = DATA_MODE;             
	LCD_DATA_PORT = ch;
	LCD_E = 1;	delay_us(40);	        
	LCD_E = 0;	delay_us(40);
}                                                
//***********************************************
// display string on lcd 
// input: pointer to string stored in flash ROM
void lcd_putsf(unsigned char flash *str) {             
	while (*str!= '\0') {
    	lcd_putc(*(str++));
    }   
}     
//************************************************
//  same as above except the string is in RAM
void lcd_puts(unsigned char *str) {             
	while (*str!= '\0') {
    	lcd_putc(*(str++));
    }   
}

and i tried microchip PIC18F452 first then i switched to Renesas M16C30280 because of its 8k RAM !!!

instead of 74164 /CD4094B i used 74HC373 it has 8 bit paralell load(i have choosen it because of faster data load), for data in i used common data bus and for chip enable diffrent pin of each one connected to the mcu individually, u can use a mux here, i used column scan , row scan can reduce ur calculations a lot but the matrix block i used for bi-color u hav to do coloumn scan, and i shorted the load enable pins of all of them to a common pin, while loading data to 74373's i disabled the data load pin, after loading data to all of them, then i enabled the pin and hold there for few milisec,this necessary to eliminate flicker though it will reduce ur frame rate , still its fast enough for animation

here is my project's pic sorry for the bad quality camera phone pic

regards

i
 
  • Like
Reactions: ismu

    ismu

    Points: 2
    Helpful Answer Positive Rating
Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top