简体   繁体   English

如何在 AVR C 中实现 arduino Uno shiftOut()?

[英]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);
  }
}

how arduino implement ShiftOut arduino 如何实现 ShiftOut

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);        
    }
}

some note to helpe you in explanition of the code一些注释可以帮助您解释代码

  1. first of all the type of 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的东西
  2. as Showen in function signature it Take 4 char as an argument如 function签名所示,它以 4 个字符作为参数
    • 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您喜欢的数据将其移出引脚
  3. the data 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中的每一位
  4. 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
  5. 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 位为零
  6. the data will writen in shift Register if the clock pin go from High to low如果时钟引脚 go 从高到低,数据将写入移位寄存器

How to implrment it with your AVR如何用你的 AVR 实现它

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

the AVR Code FOR Shift out AVR 代码 FOR 移出

// 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM