[英]How to implement arduino Uno shiftOut() in AVR C?
I am trying to control an 8x8 led matrix using shift register 74hc595.我正在尝试使用移位寄存器 74hc595 控制 8x8 LED 矩阵。 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.在正常的 Arduino 代码中,我们使用shiftOut()
function 写入 dataPin,但我在 AVR C 中尝试同样的事情时遇到了麻烦。我遇到的唯一问题是如何将数据仅发送到 dataPin移位寄存器,因为如果我使用PORTB |= data
,端口中的所有内容都会受到影响。
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
首先, uint8_t
的类型只是在某个地方的char
类型,它有类似typedef char uint8_t
的东西data pin
the pin number that you conect the data on it data pin
你连接数据的pin号clock pin
the pin number that you conect the clock on it clock pin
你连接时钟的引脚号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
bit Order
要选择哪个位 go 首先(最低有效位 go 第一个或最高有效位 go 首先),并且您可以使用一些 def.netions 为此#define LSBFIRST 0
和#define MSBFIRST 1
Val
the data you like shift it out on pins Val
您喜欢的数据将其移出引脚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
数据Val
是一个char
类型,而 Char 类型只是一个8 位,所以你将循环 8 次以获取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
1<<i
这是左移运算符,它只会创建一个位的麝香例如,如果i is equal 5
,则将创建二进制,如0b00100000
,如果i is equal to 2
,将创建二进制位,如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 val & (1<<i)
... 运算符&
是按位运算符,如果val
中的第 i 位为1
,则此表达式将给出非零值,如果val
中的第 i 位为零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 AVR 中的实现与 arduino 的实现非常相似,只是有一点点不同……您应该注意到,在 arduino 中,您只需使用一个引脚号访问该引脚,而在 arduino 使用的 Function 内部,此引脚号将被解码为端口号( PORTA,PORTB,..etc ) 和该端口内的位号
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
重要信息,您需要知道该端口只是 memory 中的一个 Register,并且该寄存器是 8 位宽,您可以使用Char pointer
访问该 Register
// 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并像这样在 main 中使用它
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这是一个快速的方法......如果你有自己的 GPIO 驱动程序(通用输入 Output 驱动程序)你可以做得更好,用于设置和清除 PINS 并使它们输入或 output
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.