I am trying to control an 8x8 led matrix using shift register 74hc595. In normal Arduino code, we use the shiftOut()
function to write to the dataPin, but what I am having trouble trying out the same thing in AVR C. The only issue I am having is how to send the data to only the dataPin of the shift register, because if I use PORTB |= data
everything in the port gets affected.
This is my code so far -
#define F_CPU 20000000L
#include <avr/io.h>
#include <avr/delay.h>
#define latchPinColumn 3
#define latchPinRow 2
#define clockPin 4
#define dataPin 5
//for looping
byte i, j;
//storing data
byte dataToSendColumn;
byte dataToSendRow;
int main()
{
//enabling output pins
DDRB |= (1 << dataPin);
DDRB |= (1 << clockPin);
DDRB |= (1 << latchPinColumn);
DDRB |= (1 << latchPinRow);
PORTB = 0x00; //setting everything to low
while(1)
{
for(i=0; i<8; i++)
{
for(j=0; j<8; j++)
{
dataToSendColumn = (1<<i);
dataToSendRow = (1<<j);
PORTB = 0x00; //setting everything to low
shiftOut(dataPin, clockPin, dataToSendColumn); //controlling the column
PORTB |= (1 << latchPinColumn); //setting latch pin for led column to high
PORTB ^= (1 << latchPinColumn); //setting latch pin for led column to low
shiftOut(dataPin, clockPin, dataToSendRow); //controlling the row
PORTB |= (1 << latchPinRow); //setting latch pin for led row to high
PORTB ^= (1 << latchPinRow); //setting latch pin for led column to low
}
}
}
}
void shiftOut(int dataP, int clock, int val)
{
//performing shiftOut in LSBFIRST method
for(i=0; i<8; i++)
{
data = val & 0b00000001;
PORTB |= data;
PORTB ^= (1^=clock);
}
}
void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val)
{
uint8_t i;
for (i = 0; i < 8; i++) {
if (bitOrder == LSBFIRST)
digitalWrite(dataPin, !!(val & (1 << i)) );
else
digitalWrite(dataPin, !!(val & (1 << (7 - i))));
digitalWrite(clockPin, HIGH);
digitalWrite(clockPin, LOW);
}
}
uint8_t
is just char
Type in some place it there is somthing like this typedef char uint8_t
data pin
the pin number that you conect the data on it clock pin
the pin number that you conect the clock on it bit Order
To choose which bit go first ( least significant bit go first or most significant bit go first ) and there are some def.netions you could use For that #define LSBFIRST 0
and #define MSBFIRST 1
Val
the data you like shift it out on pins Val
is a char
Type and Char type is just an 8 bit so you will loop 8 time to get each bit in val
1<<i
this is shift left operator it just will creat a musk of bits For examble if i is equal 5
than that will creat binary like 0b00100000
and if i is equal to 2
that will creat binary bits like 0b00000100
val & (1<<i)
... the operator &
is a bitwise and opertor this expration will give a non zero values if the i'th bit in val
is 1
and will give zero if the i'th bit in val
is Zero the implementation in AVR will be much similar to arduino implementation with a little bit difference... you should notice that in arduino you access the pin just with a pin number and inside the Function used by arduino this pin number will be decoded into port Number ( PORTA,PORTB,..etc ) and bit Number inside that port
important information you need to know that the port is just an Regester in memory and that register is 8 bit width and you code access that Register with Char pointer
// helper macros to make pin HIgh or low
#define SET_PIN(port,pinNumber) ( (port) |= (1<<pinNumber))
#define CLEAR_PIN(port,pinNumber) ( (port) &=~(1<<pinNumber) )
// defention for Bits order
#define LSBFIRST 0
#define MSBFIRST 1
// pin information
typedef struct {
volatile unsigned char * Port;
char NUmber;
}Pin;
// function implementaiton
void shiftOut(Pin dataPin, Pin clockPin, char bitOrder, char val)
{
char i;
for (i = 0; i < 8; i++) {
if (bitOrder == LSBFIRST){
(val & (1 << i))?SET_PIN(*dataPin.Port,dataPin.NUmber):CLEAR_PIN(*dataPin.Port,dataPin.NUmber);
}
else{
(val & (1 << (7 - i)))?SET_PIN(*dataPin.Port,dataPin.NUmber):CLEAR_PIN(*dataPin.Port,dataPin.NUmber);
}
// make a clockpin go from high to low
SET_PIN(*clockPin.Port,clockPin.NUmber);
CLEAR_PIN(*clockPin.Port,clockPin.NUmber);
}
}
and use it inside main like this
void main(){
//code ...
// init section
Pin data = {&PORTB,4};
Pin clock= {&PORTB,5};
// make it output
DDRB |=1<<4;
DDRB |=1<<5;
//code ...
while(1){
// code ..
// use when you need
shiftOut(data,clock,LSBFIRST,9); // this will shift out 9(0b00001001) low bit will go first
// code ...
}
}
this is a quick way... you Could make it better if you have your own GPIO Drivers (General Purpose Input Output Driver) For set and clear PIns and make them input or output
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.