0

I know this isn't exactly an Arduino question, but I'm using the Arduino IDE and feel it's close enough. So I'm working on a project that uses an ATTiny84, two SN74HC595N SIPO shift registers, and a SN74HC165 PISO shift register. Had a custom PCB printed and after a few bodge wires got everything working. It all works fine on an UNO R3, but when I moved to the ATTiny84, it quit working. Basically, I could update the '595 shift register once and it would be unresponsive after that.

I did some tinkering and narrowed the issue down to the data output from the '165 register. As wired, the 165's data line is connected to PORTB2 (physical pin 5) and when I declare it as an INPUT, the program stops working. The '595 shift registers work fine when declaring PB2 as an output or using a different pin altogether (PA5 for example).

For now, I'm planning on rewiring the '165 and doing some more testing. I'm hoping someone that knows much more than myself can help explain why this happens. Code is below.

Parts I'm using are all from digikey:

  • 296-8251-5-ND ---- SN74HC165N
  • 296-1600-5-ND ---- SN74HC595N
  • ATTINY84A-PU-ND -- ATTINY84 MCU
#define SER PORTA0 // data
#define RCLK PORTA2 // latch
#define SRCLK PORTA1 // clock
// 165 shift register
#define CLK PORTB0 // clock - arduino 7 - ATTiny PORTB0
#define SHLD PORTB1 // shift load - arduino 6 - ATTiny PORTB1
#define Qh PORTA5 // data out - arduino 5 - ATTiny PORTB2 -- THIS IS THE CULPRIT PIN
#define CLKINH PORTA3 // clock inhibit - arduino 4 - ATTiny PORTA3
// status LED
#define STATUS PORTA7
#define numCols 11
//uint8_t read[numCols];
//uint8_t oldRead[numCols];
int currentCol = 1;
#include <timer.h>
timer tim;
void setup() {
 tim.setInterval(1000);
 // 595
 pinMode(SER, OUTPUT);
 pinMode(RCLK, OUTPUT);
 pinMode(SRCLK, OUTPUT);
 //165
 pinMode(CLK, OUTPUT);
 pinMode(SHLD, OUTPUT);
 pinMode(Qh, INPUT);
 pinMode(CLKINH, OUTPUT);
 //status LED
 pinMode(STATUS, OUTPUT);
 // set initial state of 165
 digitalWrite(CLKINH, HIGH);
 digitalWrite(CLK, LOW);
 digitalWrite(SHLD, HIGH);
 write595(0xAA); // just to see something
}
void loop() {
 for(int i=0; i<numCols; i++){
 write595(currentCol);
 currentCol = currentCol <<1;
 //delay(250);
 }
 currentCol = 1;
}
void write595(uint16_t num){
 uint8_t MSB = num >> 8;
 uint8_t LSB = num;
 digitalWrite(RCLK, LOW);
 shiftOut(SER, SRCLK, MSBFIRST, MSB);
 shiftOut(SER, SRCLK, MSBFIRST, LSB);
 digitalWrite(RCLK, HIGH);
}
// uint8_t read165(void){
// uint8_t data = 0;
// // toggle shift/load to store data to the register
// digitalWrite(SHLD, LOW);
// delayMicroseconds(5);
// digitalWrite(SHLD, HIGH);
// delayMicroseconds(5);
// // shift that data out and return it to the program
// digitalWrite(CLK, HIGH);
// digitalWrite(CLKINH, LOW);
// data = shiftIn(Qh, CLK, MSBFIRST);
// digitalWrite(CLKINH, HIGH);
// return data; 
// }
Rohit Gupta
6122 gold badges5 silver badges18 bronze badges
asked Jan 20 at 0:45
3
  • 1
    add debugging code ... as it stands now, you have no way of knowing what the program is doing Commented Jan 20 at 4:10
  • 1
    Welcome to SE/Arduino! Please take the tour to learn how this site works, and read "How to Ask" and other pages of the help center. -- "Not working" does not tell us what happens instead, please edit your question to add that. While you're at it, also add a schematic of the non-working circuit, please. Commented Jan 20 at 6:51
  • 2
    A schematic would definitely help. What is "timer.h" ? Supply a link to it. Maybe it is using the "problem" pin or expecting an ISR to be defined. Depending on which Arduino core you are using for the ATtiny84 there are (possibly) different pin numbering schemes for the MCU. Also your loop is very fast. Are you sure you would see any visible effects? Commented Jan 20 at 10:35

2 Answers 2

3

PORTB0, PORTA5, etc. are not intended to be used with the Arduino pinMode, digitalRead, etc functions. These are not defined to Arduino pin numbers.

They are bit index numbers to be used with directly manipulating the PORTA and PORTB GPIO port registers. E.g. if you wanted to set GPIO PB3 high, you could use PORTB3 in an expression like PORTB |= 1 << PORTB3; Many of us don't use the named bit fields specifically for GPIO registers, since they don't make the code any more readable. Instead we'd just put 3 instead of PORTB3. If anything these bit index macros for GPIO ports have caused more confusion that they've removed.

Anyway, because they're just bit index numbers, PORTB0 and PORTA0 are both 0, PORTB1 and PORTA1 are both 1, and that pattern repeats up to 7.

Rearranging your #defines slightly it's maybe easier to see conflicts now:

// Conflicting pair; both trying to be Arduino pin 0 when later used with pinMode() etc
#define SER PORTA0 // data
#define CLK PORTB0 // clock - arduino 7 - ATTiny PORTB0
// Conflicting pair; both trying to use Arduino pin 1
#define SRCLK PORTA1 // clock
#define SHLD PORTB1 // shift load - arduino 6 - ATTiny PORTB1
// Conflicting pair when Qh is PORTB2.
#define RCLK PORTA2 // latch
#define Qh PORTA5 // data out - arduino 5 - ATTiny PORTB2 -- THIS IS THE CULPRIT PIN
// Not conflicting anything... yet.
#define CLKINH PORTA3 // clock inhibit - arduino 4 - ATTiny PORTA3

Sometimes people get away with using these PORTx# macros when using something like an ATtiny85, because it only has one port, PORTB, and the mapping has been designed to use the PORTB bit numbers as the Arduino pin numbers. But that isn't going to work out so well with an ATtiny84 what has multiple ports.

You need to consult the documentation to whatever Arduino core you're using. E.g., for ATtiny84A with ATtinycore you'd follow this:

ATtinycore pin mapping diagram for the ATttiny84, ATtiny44, and ATtiny24

Follow the grayish-blue "Arduino Pin" numbers. There are to sets. You need to choose between them depending on whether you picked clockwise or counterclockwise in the board menus.

answered Jan 20 at 22:07
-1

I ended up getting this to work. I needed to change the wiring of the 165 shift register and put its data line on PA5 (or pin 5).

Turns out that changing from "PORTxn" nomenclature didn't help (CW or CCW), however, I'm making that change as it definitely makes sense to do so. Thank you, Timemage!

To answer some other questions: I usually use Serial.print to debug, however, the ATTiny's don't have that. That's why I've included a status led on PA7. "timer.h" is a library I wrote that's bases on the blink without delay concept that has one method which returns true whenever the preset interval is up. It let's me write non-blocking code very easily.

Thanks again all!

answered Jan 23 at 3:11

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.