The only error is the 3 instead of 2 cycles. I think their use of the word "jump" is just in the general sense meaning "some opcode that gets you from one place to another". Both JMP and RJMP achieve that. I agree that if they'd said "The vector is normally a JMP to the interrupt routine, and this jump takes three clock cycles. " then that would be wrong. (obviously the 3 cycle thing is an error though).
High slewrate data on RxD0 disturbs the crystal oscillator in the AVR when it's not set to "Full swing" with the fusebits.
So either reduce the slewrate on RxD (using 10k - 100pF Low pass filter), or set the oscillator to full swing.
USART_Receive:
; Wait for data to be received
in r16, UCSRnA
sbrs r16, UDREn
rjmp USART_Receive
; Get and return received data from buffer
in r16, UDRn
ret
Here the USART Data register Empty flag is checked instead of the USART Receive Complete flag.
The fun part is that the C code example below that does have the correct code:
unsigned char USART_Receive( void )
{
/* Wait for data to be received */
while ( !(UCSRnA & (1<<RXCn)) )
;
/* Get and return received data from buffer */
return UDRn;
}
AT90CAN128: aborting a pending MOb can leave CONMOB in an unexpected state
I am not sure what kind of bug this is: could be a hardware bug or could be Atmel's library at90CANlib_3_2 being buggy AND misleading.
The library's procedure to abort a MOb that was pending consists on writing 0 to the CONMOB bits. Also, the library depends on those bits being 0 to detect a MOb as being free.
Turns out that a failed MOb (e.g. because of bus errors) will retry its process, and if its CONMOB is overwritten with 0 in that situation there is a rare chance that the CONMOB will jump back to its old value. So any routine testing for CONMOB==0 will consider the MOb busy. Result: a MOb leaked and unusable until reset.
I wrote Atmel about this and their answer was that:
Quote:
If you want to abort CAN communications, I would instead recommend using ABRQ in CANGCON as the means to abort. CANCDMOB is not affected by the abort, so you would still have to manage it.
... but that is not a good solution, because ABRQ aborts all MObs. I only wanted to abort one MOb.
Also they said, ...
Quote:
CANCDMOB really does not indicate that a MOB is "free" in the sense that it is ready for the next transmission - other bits indicate this; the user manual is clear that CONMOB bits are not cleared once communication is performed...
Which is true according to the documentation, which mentions that CANEN is the register to check for availability of MObs. But that means that the library is pretty b0rked, since it never even refers to the CANEN registers.
Also, the manual mentions repeatedly that the CONMOB is not expected to change by itself, not even after a reset. Which makes me think that this is actually a hardware bug (no?).
Anyway, my minimal workaround is: when aborting a MOb, write 0 to CONMOB, check that the corresponding CANEN bit is 0, and rewrite the 0 to CONMOB.
Alternatively, to search for free MObs, stop checking CONMOB and switch to checking CANEN.
Posted by dbvanhorn: Fri. Jan 2, 2015 - 07:52 PM(Reply to #55)
1
2
3
4
5
Total votes: 1
The low power oscillator itself is a bug imho. I have seen it cause all manner of glitchy, impossible to debug problems, which are magically cured by going back to the full swing oscillator.
Two typing errors in ATmega64M1 datasheet (7647K–AVR–12/13 )
19.2.2 Current Source for Low Cost Traducer An external transducer based on variable resistor can be connected to the current source. This ca be for instance: ● A thermistor, or temperature-sensitive resistor, used as a temperature sensor ● A CdS photoconductive cell, or luminosity-sensitivity resistor, used as a luminosity sensor. Using the current source with this type of transducer eliminates the need for additional parts otherwise required in resistor network or Wheatstone bridge.
Many AVR8 datasheets, including modern versions for e.g. Mega48 family and Mega164 family, have the "I/O pin input hysteresis vs. VCC" graph in Typical Characteristics scaled in millivolts (mV). It should be volts (V), as in e.g. Tiny1634 sheet.
You can put lipstick on a pig, but it is still a pig.
I've never met a pig I didn't like, as long as you have some salt and pepper.
Posted by Stub_Mandrel: Sun. Mar 27, 2016 - 10:55 AM
1
2
3
4
5
Total votes: 0
Device: MEGA644P family
Summary: Datasheet errata
Datasheet assembler examples (notably the USART) do not appear to have been updated to reflect that some registers are now outside the 'magic 32' where in and out instructions work and therefore lds and sts need to be sued, and the example code will throw errors.
Datasheet assembler examples (notably the USART) do not appear to have been updated to reflect that some registers are now outside the 'magic 32' where in and out instructions work and therefore lds and sts need to be sued, and the example code will throw errors.
Thank you.
Note that the 'magic 32' are for the single-instruction bit-manipulation and bit-testing instructions like SBI/CBI/SBIS/SBIC. Instructions like IN/OUT will work on all 64 I/O registers.
"Experience is what enables you to recognise a mistake the second time you make it."
"Good judgement comes from experience. Experience comes from bad judgement."
"Wisdom is always wont to arrive late, and to be a little approximate on first possession."
"When you hear hoofbeats, think horses, not unicorns."
"Fast. Cheap. Good. Pick two."
"We see a lot of arses on handlebars around here." - [J Ekdahl]
stub does your datasheet contain a little note at the bottom of the examples which says:
Note: 1. See “About Code Examples” on page 8.
which in turn says
3.2 About Code Examples This documentation contains simple code examples that briefly show how to use various parts of the device. Be aware that not all C compiler vendors include bit definitions in the header files and interrupt handling in C is compiler dependent. Please confirm with the C compiler documentation for more details. The code examples assume that the part specific header file is included before compilation. For I/O registers located in extended I/O map, "IN", "OUT", "SBIS", "SBIC", "CBI", and "SBI" instructions must be replaced with instructions that allow access to extended I/O. Typically "LDS" and "STS" combined with "SBRS", "SBRC", "SBR", and "CBR".
Anyway assembler tragics use macros to overcome that sort comings
AVR001: Conditional Assembly and portability macros
13.10 Clock and Event Output
It is possible to output the peripheral clock and any of the event channels to the port pins (using EVCTRL register). This
can be used to clock, control, and synchronize external functions and hardware to internal device timing. The output port
pin is selectable. If an event occurs, it remains visible on the port pin as long as the event lasts; normally one peripheral
clock cycle.
Summary: PD0 incorrectly listed as RXD1 (USART1 Input Pin) on page 98 under "17.3.3. Alternate Functions of Port D". Correct assignment for PD0 is RXD0 (USART0 Input Pin) as elsewhere in datasheet (including "Table 6-1. PORT Function Multiplexing"). Also makes ATmega328PB Xplained Mini schematic more logical: unlikely to use USART0 for TXD and USART1 for RXD.
The latest (0856L - Nov '16) revision of the Atmel AVR Instruction Set Manual gives the mistaken impression that an intermediary register will often be needed with the EOR instruction. In section 58.1 (p91), among the operands, the bitmask register Rr is restricted to R0 - R3. You can't use LDI to load a bitmask register with that restriction: LDI requires R16 - R31.
The problem is a typo - a missing '1': the restriction on Rr should be R0 - R31. This is hinted at by the example (in 58.2 on the same page) which uses R4 for Rr; that would be wrong if the limit of R3 were correct. More significant, the opcode shows five bits for Rr (R0 - R31) not two as it would if the limit of R3 were correct.
It should. It's usually the input delayed by one byte.
Note that the command in question is "Programming Enable". The echo-to-MISO likely isn't enabled until programming is enabled. That happens after the $53 is received, so echoing likely starts on the 3rd byte, echoing the second byte, $53.
Note that device datasheets are not definitive, but seem to support this interpretation:
Note that I have not confirmed on hardware what @MASIP has reported above.
"Experience is what enables you to recognise a mistake the second time you make it."
"Good judgement comes from experience. Experience comes from bad judgement."
"Wisdom is always wont to arrive late, and to be a little approximate on first possession."
"When you hear hoofbeats, think horses, not unicorns."
"Fast. Cheap. Good. Pick two."
"We see a lot of arses on handlebars around here." - [J Ekdahl]
The latest complete datasheet (DS40001906C, dated 2018-02-22) still gives conflicting pinouts for serial ISP.
"Figure 32-6. Serial Programming and Verify, VCC = 1.8 - 5.5V" on p400 shows MOSI, MISO and SCK as PB5, PB6 and PB7 respectively. That's wrong; it appears to be copied from the datasheet for the ATmega324PB (for which those pins are correct).
For the ATmega328PB the correct pins for MOSI, MISO and SCK are PB3, PB4 and PB5 respectively. The datasheet has that correct further down the page, in "Table 32-15. Pin Mapping Serial Programming". (The schematic for the 328PB Xplained Mini board also shows the correct pins.)
Below Table 32-15 there also appears this confusing note: "The pin mapping for SPI programming is listed. Not all parts use the SPI pins dedicated for the internal SPI interface." What it means is this: The pin mapping for serial ISP is listed. There are pins dedicated for the internal SPI but not all parts use them for ISP.
I believe there an error in the ATmega48A.../328/P datasheet, dated 2018, DS40002061A.
On page 131, Section 16.9.1, the second paragraph starting "The Input Capture ..." states the need to deal with "resolution of the counter", but I think they mean "range of the counter".
Edit: Or am I missing something with respect to the term "resolution"?
Summary: Errors in datasheet 7766J (04/2016), Chapter 32 "Instruction Set Summary"
I've tested the CALL and RET instructions, and their #Clocks values are wrong.
Since the Program Counter (PC) is 16 bits wide:
- the CALL instruction pushes 2 bytes on the stack,
- the CALL instruction takes only 4 cycles -- instead of 5,
- the RET instruction takes only 4 cycles -- instead of 5.
Since the wrong values might come from the copy of data corresponding to a device with a larger memory space, the values for the RCALL, ICALL, EICALL and RETI instructions should also be checked.
Posted by 12oclocker: Mon. Sep 23, 2019 - 03:43 PM
1
2
3
4
5
Total votes: 1
ATTINY1614
Datasheet says on pg337; "When the USART is set in one-wire mode, the transmitter and the receiver share the same RxD I/O pin."; (that is wrong)
One-Wire pin is the TXD pin, NOT THE RXD PIN
Microchip has confirmed that TXD is the correct pin for One-Wire. I'm in the process of trying to get Microchip to update the datasheet.
Also not specified in the datasheet for One-Wire mode...
If TX pin is set as output, ODME "Open Drain Mode Enable" does not work.
so TX port must NOT be set as output when using ODME "Open Drain Mode Enable".
This is Not specified in the datasheet.
The following statement from pg340 about one wire setup is vague.
For setting the USART in One-Wire mode, the following initialization sequence is recommended:
1) Set the TxD/RxD pin value high, and optionally set the XCK pin low.
*Needs clarification, what does "Set the TxD pin value high" mean, pullup resistors? or set as output?
*testing shows that in open drain mode, pin should NOT be set as output
2) Optionally, write the ODME bit in the USARTn.CTRLB register to '1' for Wired-AND functionality.
3) Set the TxD/RxD and optionally the XCK pin as an output.
4) Select the baud rate and frame format.
5) Select the mode of operation (enables XCK pin output in Synchronous mode).
6) Enable the transmitter or the receiver, depending on the usage
Tested and working method for 1 wire.
1) Do NOT set TxD pin as output
2) Enable Pullup Resistor on TxD pin if NOT using external pullup.
3) set bit LBME "Loop-back Mode Enable"
4) set bit ODME "Open Drain Mode Enable"
5) Use TxD pin for Transmit and Receive operations.
6) Enable the transmitter or the receiver, depending on the usage
New silicon errata found on ATMEGA324PB: OC1B signal on pin PD4 stops working if USART1 is enabled.
Case 00496661 submitted to Microchip.
This is really annoying, because in my design I can't use my second stepper motor (step signal connected to OC1B) together with the second UART. (I Use 2 steppers and 2 UART's, so I cannot use other channels).
Here is a minimal code example to demonstrate the bug.
#include <avr/io.h>
#include <avr/interrupt.h>
// Proof of concept of silicon errata on ATMEGA324PB: OC1B signal on pin PD4 stops working if USART1 is enabled
// Minimal working example, some registers are already set correctly by power on default value
int main()
{
DDRD |= (1 << 4); // Set OC1B (PD4) as output
TCCR1A = (1 << COM1B0); // Toggle OC1B (PD4) on compare
TCCR1B = 0x02; // Start timer (divide by 8)
// Pin OC1B (PD4) is now generating pulses at frequency fOsc / 65536 / 8 / 2 (check with blinking LED)
// Uncomment line below to demonstrate silicon errata on ATMEGA324PB. Pulses on pin OC1B (PD4) will stop after uncommenting.
// UCSR1B = (1<<RXEN1) | (1<<TXEN1);
// As soon as USART1 is enabled, Pin PD4 is disconnected from OC1B and stops generating pulses.
// It seems that alternate port function XCK1 is disturbing control of pin PD4
// This should NOT happen since the USART is NOT in synchronous mode. (UMSEL in TCCR1C is 0 by default)
The AVR Universal Serial Interface (USI) Three-wire external clock modes are compliant with SPI modes 1 and 3. The datasheet (e.g., ATtiny84A) partially correctly states that the "USI clock modes correspond to SPI data modes 0 and 1". However, the datasheet USI Three-wire Mode Timing Diagram figure and supporting text are ambiguous and/or fundamentally incorrect with regards to how the USI actually functions; most importantly, the described clock edge phase association with DI-sample/DO-change events are either inconsistent or wrong.
I have notified Microchip, who said they are looking into it.
The following figure summarizes the USI external clock modes functionality:
The following ATtiny84A program characterizes the USI DI-sample/DO-change timing on a standalone chip without need for an oscilloscope to observe results (although a scope is very useful):
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/cpufunc.h>
#include <util/delay.h>
#include <stdint.h>
#include <stdbool.h>
// Purpose:
// Discover USI Three-wire external clock mode DI and DO timing wrt USCK
// without external connections to device pins (self-acquisition).
// Results summary (USICS1 = 1):
// USICS0 = 0 with normally high USCK: This USI usage mode looks the same as SPI mode 3 (CPOL=1, CPHA=1)
// USICS0 = 1 with normally low USCK: This USI usage mode looks the same as SPI mode 1 (CPOL=0, CPHA=1)
// USICS0 = 0 with normally low USCK: This USI usage mode does not look any SPI mode
// USICS0 = 1 with normally high USCK: This USI usage mode does not look any SPI mode
// Method:
// 1. Manually generate 16 USCK edges for each simulated transfer.
// 2. Use Pin Change interrupts for DO and USCK to capture time, pin state, and USICNT for each pin state change.
// 3. Apply simulated DI pin input, then capture the time when it is sampled by the USI for each Data register bit.
// Detailed observations for all combinations of USICS0 and normal USCK clock states:
#define USICS0_VALUE 0 // USI clock source edge select (0 or 1): 0=="positive edge", 1=="negative edge"
#define NORMAL_USCK_STATE 1 // USI USCK normal (before and after transfer) state (0 or 1): 0==low, 1==high
// USICS0 = 0 with normally high USCK (This USI usage mode looks the same as SPI mode 3 (CPOL=1, CPHA=1)):
// DO is changed on leading (falling) USCK edges 1(MSB),3(b6),5(b5),7(b4),9(b3),11(b2),13(b1),15(LSB); (not changed at write to USIDR)
// DI is sampled on trailing (rising) USCK edges 2(MSB),4(b6),6(b5),8(b4),10(b3),12(b2),14(b1),16(LSB)
//#define USICS0_VALUE 1 // USI clock source edge select (0 or 1): 0=="positive edge", 1=="negative edge"
//#define NORMAL_USCK_STATE 0 // USI USCK normal (before and after transfer) state (0 or 1): 0==low, 1==high
// USICS0 = 1 with normally low USCK (This USI usage mode looks the same as SPI mode 1 (CPOL=0, CPHA=1)):
// DO is changed on leading (rising) USCK edges 1(MSB),3(b6),5(b5),7(b4),9(b3),11(b2),13(b1),15(LSB); (not changed at write to USIDR)
// DI is sampled on trailing (falling) USCK edges 2(MSB),4(b6),6(b5),8(b4),10(b3),12(b2),14(b1),16(LSB)
// MSB is sampled (DI) on 2nd USCK edge (USICNT=1 to 2); LSB is sampled (DI) on 16th USCK edge (USICNT=15 to 0)
//#define USICS0_VALUE 0 // USI clock source edge select (0 or 1): 0=="positive edge", 1=="negative edge"
//#define NORMAL_USCK_STATE 0 // USI USCK normal (before and after transfer) state (0 or 1): 0==low, 1==high
// USICS0 = 0 with normally low USCK (This USI usage mode does not look any SPI mode):
// DO is changed to MSB at write to USIDR,
// then on trailing (falling) USCK edges 2(b6),4(b5),6(b4),8(b3),10(b2),12(b1),14(LSB),16(next MSB)
// DI is sampled on mixed USCK edges; rising 3(MSB),5(b6),7(b5),9(b4),11(b3),13(b2),15(b1), and falling 16(LSB)
//#define USICS0_VALUE 1 // USI clock source edge select (0 or 1): 0=="positive edge", 1=="negative edge"
//#define NORMAL_USCK_STATE 1 // USI USCK normal (before and after transfer) state (0 or 1): 0==low, 1==high
// USICS0 = 1 with normally high USCK (This USI usage mode does not look any SPI mode):
// DO is changed to MSB at write to USIDR,
// then on trailing (rising) USCK edges 2(b6),4(b5),6(b4),8(b3),10(b2),12(b1),14(LSB),16(next MSB)
// DI is sampled on mixed USCK edges; falling 3(MSB),5(b6),7(b5),9(b4),11(b3),13(b2),15(b1), and rising 16(LSB)
// Hardware abstraction for bit access:
struct bits
{
uint8_t b0:1;
uint8_t b1:1;
uint8_t b2:1;
uint8_t b3:1;
uint8_t b4:1;
uint8_t b5:1;
uint8_t b6:1;
uint8_t b7:1;
} __attribute__((__packed__));
#define BIT(portLetter, bitNumber, registerName) ((*(volatile struct bits*)®isterName##portLetter).b##bitNumber)
// portLetter = A-D, bitNumber = 0-7, registerName = "PORT", "PIN", or "DDR"
#define INPUT 0 // DDR bit = input
#define OUTPUT 1 // DDR bit = output
// Pin usage map:
// ATtiny84A Port Functions
// Name Num FuncA FuncB FuncC FuncD FuncE FuncF Usage
// ---- --- ----- ----- ----- ----- ----- ----- -----
// PA7 6 ADC7 OC0B ICP1 - - PCINT7 ==
// PA6 7 ADC6 DI SDA MOSI OC1A PCINT6 == USI DI
// PA5 8 ADC5 DO MISO OC1B - PCINT5 == USI DO, PCINT5
// PA4 9 ADC4 USCK SCL T1 - PCINT4 == USI USCK, PCINT4
// PA3 10 ADC3 T0 - - - PCINT3 ==
// PA2 11 ADC2 AIN1 - - - PCINT2 ==
// PA1 12 ADC1 AIN0 - - - PCINT1 ==
// PA0 13 ADC0 AREF - - - PCINT0 == scope trigger
//
// PB3 4 RESET dW - - - PCINT11 == dW
// PB2 5 INT0 OC0A CKOUT - - PCINT10 ==
// PB1 3 XTAL2 - - - - PCINT9 == resonator
// PB0 2 XTAL1 CLKI - - - PCINT8 == resonator
//
// Vcc 1
// GND 14
// Pin assignments
#define USI_DI(r) BIT(A, 6, r) // USI 3-wire mode DI
#define USI_DO(r) BIT(A, 5, r) // USI 3-wire mode DO
#define USI_USCK(r) BIT(A, 4, r) // USI 3-wire mode USCK
#define SCOPE_TRIG(r) BIT(A, 0, r) // scope trigger
#define PCINT_DO PCINT5 // DO pin change interrupt mask bit
#define PCINT_USCK PCINT4 // USCK pin change interrupt mask bit
// Constants
const double timeTick = 40e-6; // time clock tick length (sec)
#define nEdges 16 // USCK edges per transfer
#define nBits 8 // data bits per transfer
const uint8_t endOfTime = 255; // time stops here
const uint8_t delayUsck = 10; // delay before first USCK edge (use 10 to "tag" 1st edge for capture readability)
const uint8_t usckWidth = 10; // half of USCK period (use 10 to "tag" edges in multiples of 10 for capture readability)
const uint8_t txData = 0xaa; // DO transmit data--need alternating bit values to force DO change at each update
const double delayTransfer = 2 * usckWidth * timeTick; // delay between transfers (sec)
// RAM variables
volatile uint8_t time; // runs from 0 to 255 * timeTick seconds
volatile uint8_t tNextEdge; // scheduled time for USCK edge output change
volatile uint8_t pinChangeCount; // DO/USCK pin change counter (pin change capture buffer index)
volatile uint8_t captureTimeUsck[nEdges]; // capture buffer for time of USCK pin change
volatile uint8_t captureStateUsck[nEdges]; // capture buffer for USCK pin state at pin change
volatile uint8_t captureUsicntUsck[nEdges]; // capture buffer for USICNT at USCK pin change
volatile uint8_t captureTimeDo[nEdges]; // capture buffer for time of DO pin change
volatile uint8_t captureStateDo[nEdges]; // capture buffer for DO pin state at pin change
volatile uint8_t captureUsicntDo[nEdges]; // capture buffer for USICNT at DO pin change
volatile uint8_t captureTimeDi[nBits]; // capture buffer for time of DI pin sample==1 for each USI Data Register Rx bit
volatile uint8_t delayDi; // DI pin stimulus (pin state set to 1) delay
volatile uint8_t bitDi; // DI capture bit number (DI capture buffer index)
static inline void Break(void)
{
asm volatile("break\n\t"::); // breakpoint instruction
}
ISR(PCINT0_vect)
{
// USI DO and USCK pin change interrupt (handle only one at a time)
if ( PCMSK0 & (1<<PCINT_DO) )
{
captureStateDo[pinChangeCount] = USI_DO(PIN); // capture DO pin state
captureTimeDo[pinChangeCount] = time; // absolute timestamp (includes delayUsck)
captureUsicntDo[pinChangeCount] = USISR & ((1<<USICNT3) | (1<<USICNT2) | (1<<USICNT1) | (1<<USICNT0) ); // capture USI USCK edge counter
}
else if ( PCMSK0 & (1<<PCINT_USCK) )
{
captureStateUsck[pinChangeCount] = USI_USCK(PIN); // capture USCK pin state
captureTimeUsck[pinChangeCount] = time; // absolute timestamp (includes delayUsck)
captureUsicntUsck[pinChangeCount] = USISR & ((1<<USICNT3) | (1<<USICNT2) | (1<<USICNT1) | (1<<USICNT0) ); // capture USI USCK edge counter
}
if ( pinChangeCount < nEdges )
{
pinChangeCount++;
}
}
ISR(TIM0_COMPA_vect, ISR_NOBLOCK) // non-blocking to allow USI DO pin change ISR
{
// Time clock tick service
// DI stimulus
if ( time == delayDi )
{
USI_DI(PORT) = 1; // set USI DI pin
_NOP(); _NOP(); // ensure sample setup time (input synchronizer delay) is met in case USCK edge is scheduled for same time
}
// USCK generator
if ( (USISR & (1<<USIOIF)) == 0 )
{
if ( time == tNextEdge ) // time for next edge?
{
USI_USCK(PIN) = 1; // toggle USCK pin
tNextEdge = time + usckWidth; // schedule next edge
}
}
// If no more time, then stop time clock
if ( time == endOfTime )
{
TIMSK0 = 0;
}
time++;
}
void RunTransferClockAndDiStim( void )
{
USI_DI(PORT) = 1; // scope trigger
USI_DI(PORT) = 0; // clear USI DI pin
USIDR = txData; // at USIDR write: if USCK(pin) == USICS0_VALUE, then DO is changed to MSB, else DO unchanged
_delay_us( delayTransfer * 1e6 );
cli();
time = 0; // reset time
tNextEdge = delayUsck; // schedule first USCK edge
USISR = 1<<USIOIF; // clear USI USCK edge counter overflow flag, and reset count
TIMSK0 = 1<<OCIE0A; // enable time interrupt; start transfer
sei();
while ( (TIMSK0 & (1<<OCIE0A)) != 0 ); // wait until ISR stops time clock
}
int main(void)
{
uint8_t i;
USI_DI(DDR) = OUTPUT;
USI_DO(DDR) = OUTPUT;
USI_USCK(DDR) = OUTPUT;
SCOPE_TRIG(DDR) = OUTPUT;
USI_USCK(PORT) = NORMAL_USCK_STATE; // when does this need to occur wrt USISR, USICR?
SCOPE_TRIG(PORT) = 0;
_delay_us( 10 * delayTransfer * 1e6 );
// Configure Timer/Counter 0 (8-bit) for use as time clock
// Mode 2, Clear Timer on Capture (CTC), TOP = OCR0A
TCCR0A = 2<<WGM00 | 0<<COM0A0; // non-PWM, OC0A/OC0B disconnected
//TCCR0B = 1<<CS00; // 1x prescale
//TCCR0B = 2<<CS00; // 8x prescale
TCCR0B = 3<<CS00; // 64x prescale
//TCCR0B = 4<<CS00; // 256x prescale
//TCCR0B = 5<<CS00; // 1024x prescale
OCR0A = ((timeTick)*F_CPU)/64 - 1;
//TIMSK0 = 1<<OCIE0A; // enable time interrupt
USICR = (1<<USIWM0) | (1<<USICS1) | (USICS0_VALUE<<USICS0); // USI mode = 3-wire; clock source = external
// Pre-fill capture buffers with invalid data that indicates non-capture
for ( i = 0; i < nEdges; i++ )
{
captureTimeUsck[i] = 0;
captureStateUsck[i] = 255;
captureUsicntUsck[i] = 255;
captureTimeDo[i] = 0;
captureStateDo[i] = 255;
captureUsicntDo[i] = 255;
}
sei();
GIMSK = 1<<PCIE0;
// Discover USCK change timing/selftest (only need single transfer)
pinChangeCount = 0;
PCMSK0 = 1<<PCINT_USCK; // enable only USI USCK pin change interrupt
RunTransferClockAndDiStim(); // let pin change ISR capture USCK change timing
// Discover DO update (USI Data Register shifted out) timing (only need single transfer)
pinChangeCount = 0;
PCMSK0 = 1<<PCINT_DO; // enable only USI DO pin change interrupt
RunTransferClockAndDiStim(); // let pin change ISR capture DO update timing
GIMSK = 0; // disable external interrupts
// Discover DI sample timing for each USI Data Register bit shifted in
delayDi = endOfTime; // set DI delay sweep to initial value (sweep from after last (LSB) down to first (MSB) bit)
for ( bitDi = 0; bitDi < nBits; bitDi++ ) // watch for last bit shifted in (LSB) first
{
do
{
RunTransferClockAndDiStim(); // let time clock ISR stimulate DI at time==delayDi
if ( USIBR & (1<<bitDi) ) // did this bit detect DI stimulus in this transfer?
{
captureTimeDi[bitDi] = delayDi; // yes, capture DI delay timestamp (absolute, includes delayUsck)
SCOPE_TRIG(PORT) = 1;
SCOPE_TRIG(PORT) = 0;
break; // skip to next bit, starting with capture delay of this bit
}
else
{
delayDi--; // no, try next DI stimulus delay for this bit
}
}
while ( delayDi >= 0 ); // should never get to delayDi==0 (should detect MSB before)
}
Break();
}
The following ATmega328P SPI master and ATtiny84A USI Three-wire mode slave programs demonstrate which USI external clock modes are compliant with SPI modes, and which are not:
ATmega328P SPI master code:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdint.h>
// Test data transfer exerciser using SPI in Master mode
#define SPI_MODE_CPOL_CPHA 0 // clock polarity and phase, [CPOL:CPHA] = 0, 1, 2, or 3
// SPI mode 0 (CPOL=0, CPHA=0): SCK idle low; read MISO on SCK lead (rise); write MOSI on SCK trail (fall) or half SCK cycle before 1st lead (rise); MOSI normally high (regardless of last bit)
// SPI mode 2 (CPOL=1, CPHA=0): SCK idle high; read MISO on SCK lead (fall); write MOSI on SCK trail (rise) or half SCK cycle before 1st lead (rise); MOSI normally high (regardless of last bit)
// SPI mode 1 (CPOL=0, CPHA=1): SCK idle low; read MISO on SCK trail (fall); write MOSI on SCK lead (rise); MOSI normally same as last bit
// SPI mode 3 (CPOL=1, CPHA=1): SCK idle high; read MISO on SCK trail (rise); write MOSI on SCK lead (fall); MOSI normally same as last bit
// Hardware abstraction for bit access:
struct bits
{
uint8_t b0:1;
uint8_t b1:1;
uint8_t b2:1;
uint8_t b3:1;
uint8_t b4:1;
uint8_t b5:1;
uint8_t b6:1;
uint8_t b7:1;
} __attribute__((__packed__));
#define BIT(portLetter, bitNumber, registerName) ((*(volatile struct bits*)®isterName##portLetter).b##bitNumber)
// portLetter = A-D, bitNumber = 0-7, registerName = "PORT", "PIN", or "DDR"
#define INPUT 0 // DDR bit = input
#define OUTPUT 1 // DDR bit = output
// ATmega328P pin assignments
#define SPI_SS_(r) BIT(B, 2, r) // SPI slave select -- output to slave
#define SPI_MOSI(r) BIT(B, 3, r) // SPI MOSI -- output to slave
#define SPI_MISO(r) BIT(B, 4, r) // SPI MISO -- input from slave
#define SPI_SCK(r) BIT(B, 5, r) // SPI SCK -- output to slave
#define ERROR_LED_(r) BIT(D, 1, r) // transfer integrity error indicator (note: active-low)
const double WAIT_SLAVE_SELECT = 2.0e-6; // wait time (seconds) for slave to prepare for transfer after select
const double WAIT_SLAVE_DESELECT = 1.0e-6; // wait time (seconds) for slave to process Tx data after deselect
const uint8_t TX_ONLY_MSB_AND_LSB = 0x81; // Tx only MSB and LSB to highlight failure mode and for better trace readability
static uint8_t txData;
static uint8_t rxData;
int main(void)
{
cli();
SPI_MISO(DDR) = INPUT;
SPI_SS_(DDR) = OUTPUT;
SPI_MOSI(DDR) = OUTPUT;
SPI_SCK(DDR) = OUTPUT;
ERROR_LED_(DDR) = OUTPUT;
SPCR = (0<<SPIE) | (1<<SPE) | (0<<DORD) | (1<<MSTR) | ((SPI_MODE_CPOL_CPHA) << CPHA); // master, MSB-first
//SPCR |= 0<<SPR0; SPSR = 1<<SPI2X; // Fsck = Fclk/2
//SPCR |= 0<<SPR0; // Fsck = Fclk/4
//SPCR |= 1<<SPR0; SPSR = 1<<SPI2X; // Fsck = Fclk/8
SPCR |= 1<<SPR0; // Fsck = Fclk/16
//SPCR |= 2<<SPR0; SPSR = 1<<SPI2X; // Fsck = Fclk/32
//SPCR |= 2<<SPR0; // Fsck = Fclk/64
//SPCR |= 3<<SPR0; SPSR = 1<<SPI2X; // Fsck = Fclk/64
//SPCR |= 3<<SPR0; // Fsck = Fclk/128
ERROR_LED_(PORT) = 1; // (note: active-low error indicator)
SPI_SS_(PORT) = 1; // deselect slave
// To see failure on scope, trigger on ERROR_LED_ or SPI_SS_ positive-pulse-width-greater-than non-error condition width
// To see success on scope, trigger on SPI_SS_ positive-pulse-width-less-than error condition width
// Repeatedly transmit same (fixed) data; expect exact data (echo) received from slave
// after data pipeline fills/flushes on first transfer.
txData = TX_ONLY_MSB_AND_LSB;
while ( 1 )
{
SPI_SS_(PORT) = 0; // select slave
_delay_us( WAIT_SLAVE_SELECT * 1.0e6 ); // wait for slave to prepare for transfer
SPDR = txData; // start transfer with Tx data
while ( (SPSR & (1<<SPIF)) == 0 ); // wait for transfer to finish
rxData = SPDR; // get Rx data
SPI_SS_(PORT) = 1; // deselect slave
_delay_us( WAIT_SLAVE_DESELECT * 1.0e6 ); // wait for slave to process Tx data
if ( rxData != txData ) // check Rx data integrity -- expect echo of previous Tx data
{
ERROR_LED_(PORT) = 0;
// Extend SPI_SS_=1 width for scope trigger on pulse-width-greater-than non-error condition width
_delay_us( 2.0 * WAIT_SLAVE_DESELECT * 1.0e6 );
ERROR_LED_(PORT) = 1;
}
}
}
ATtiny84A USI Three-wire mode slave code:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdint.h>
// Echo received test data using slave USI in Three-wire mode, external clock
#define USICS0_VALUE 0 // clock source edge select (0 or 1): 0=="positive edge", 1=="negative edge"
// Test observations for USI slave (ATtiny84A @20MHz) in both external clock modes, USICS1=1 and USICS0=0/1
// with real SPI master (ATmega328P @16MHz) in modes 0/1/2/3 with Fusck = 1 MHz:
// SPI mode 0 (CPOL=0, CPHA=0): SCK idle low; read MISO on SCK lead (rise); write MOSI on SCK trail (fall) or half SCK cycle before 1st lead (rise); MOSI normally high (regardless of last bit)
// SPI mode 2 (CPOL=1, CPHA=0): SCK idle high; read MISO on SCK lead (fall); write MOSI on SCK trail (rise) or half SCK cycle before 1st lead (rise); MOSI normally high (regardless of last bit)
// SPI mode 1 (CPOL=0, CPHA=1): SCK idle low; read MISO on SCK trail (fall); write MOSI on SCK lead (rise); MOSI normally same as last bit
// SPI mode 3 (CPOL=1, CPHA=1): SCK idle high; read MISO on SCK trail (rise); write MOSI on SCK lead (fall); MOSI normally same as last bit
// USI slave USICS0=0 / SPI master mode 0 (CPOL=0, CPHA=0): DI=0x81 DO=0x03 (fail) "usitest_00.bmp"
// USI slave USICS0=0 / SPI master mode 1 (CPOL=0, CPHA=1): DI=0x81 DO=various (fail) "usitest_01.bmp"
// USI slave USICS0=0 / SPI master mode 2 (CPOL=1, CPHA=0): DI=0x81 DO=various (fail) "usitest_02.bmp"
// USI slave USICS0=0 / SPI master mode 3 (CPOL=1, CPHA=1): DI=0x81 DO=0x81 (pass) "usitest_03.bmp"
// USI slave USICS0=1 / SPI master mode 0 (CPOL=0, CPHA=0): DI=0x81 DO=various (fail) "usitest_10.bmp"
// USI slave USICS0=1 / SPI master mode 1 (CPOL=0, CPHA=1): DI=0x81 DO=0x81 (pass) "usitest_11.bmp"
// USI slave USICS0=1 / SPI master mode 2 (CPOL=1, CPHA=0): DI=0x81 DO=0x03 (fail) "usitest_12.bmp"
// USI slave USICS0=1 / SPI master mode 3 (CPOL=1, CPHA=1): DI=0x81 DO=various (fail) "usitest_13.bmp"
// Hardware abstraction for bit access:
struct bits
{
uint8_t b0:1;
uint8_t b1:1;
uint8_t b2:1;
uint8_t b3:1;
uint8_t b4:1;
uint8_t b5:1;
uint8_t b6:1;
uint8_t b7:1;
} __attribute__((__packed__));
#define BIT(portLetter, bitNumber, registerName) ((*(volatile struct bits*)®isterName##portLetter).b##bitNumber)
// portLetter = A-D, bitNumber = 0-7, registerName = "PORT", "PIN", or "DDR"
#define INPUT 0 // DDR bit = input
#define OUTPUT 1 // DDR bit = output
// ATtiny84A pin assignments
#define SPI_SS_(r) BIT(A, 7, r) // [Pin# 6] SPI slave select -- input from master
#define USI_DI(r) BIT(A, 6, r) // [Pin# 7] SPI MOSI -- input from master
#define USI_DO(r) BIT(A, 5, r) // [Pin# 8] SPI MISO -- output to master
#define USI_USCK(r) BIT(A, 4, r) // [Pin# 9] SPI SCK -- input from master
int main(void)
{
cli();
SPI_SS_(DDR) = INPUT;
USI_DI(DDR) = INPUT;
USI_USCK(DDR) = INPUT;
USI_DO(DDR) = OUTPUT;
USICR = (1<<USIWM0) | (1<<USICS1) | (USICS0_VALUE<<USICS0); // USI mode = 3-wire; clock source = external
while( 1 )
{
if ( SPI_SS_(PIN) == 1 )
{
USI_DO(DDR) = INPUT; // slave is deselected; float DO
USISR = 1<<USIOIF; // synch/reset USCK edge counter, and clear overflow flag
USIDR = USIBR; // pre-load Tx test data
}
else
{
USI_DO(DDR) = OUTPUT; // slave is deselected; drive DO (master waits enough time)
if ( USISR & (1<<USIOIF) ) // transfer complete? (master supplies clock)
{
USISR = 1<<USIOIF; // reset USCK edge counter, and clear overflow flag
}
}
}
}
Summary: PCINT on PE pins documentation is wrong and incomplete
Details:
In the datasheet DS40001908A:
* page 427: the register number for PCMSK4 is given as 0x74, but it is really 0x75
* page 16: the PCINT34..PCINT38 functionality on pins PE2..PE6 is missing in the table
* page 104: the PCINT32..PCINT38 functionality on PE is missing in tables 16-15 and 16-16
Posted by paulkapil08: Fri. May 14, 2021 - 11:49 AM
1
2
3
4
5
Total votes: 0
The latest version of the AVR Instruction Set Reference (Rev. 0856F–AVR–05/08) Has a section marked "SPM #2" That shows an additional form of SPM. The shown opcode for forms i-iii ("SPM") cannot be correct as it conflicts with "BCLR 4" (also known as "CLS") get-mobdro.com
#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."
#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."
On page 117 of my ATmega328P datasheet the document clearly show the DDRB register with its corresponding bit names: DDRB7...DDRB0
Yet, when I input a code line in Studio7 , I get an indication that DDRB1 is not a valid constant name.
DDRB |= (1 << DDRB1) ; // an underscore appear on DDRB1
DDRB |= (1 << DDB1) ; // instead DDB1 seems to be the correct name
Also, if I open the DDRB file with "Goto Implementation" feature of Studio7, I find that , indeed, the iom328p.h file open and show the correct name for all DDRB bits are "DDB1"
So, I have to conclude that the Microchip Datasheet for the ATmega328P is wrong.
The asm include file for the M328 does not have DDRBx but DDBx
; DDRB - Port B Data Direction Register
.equ DDB0 = 0 ; Port B Data Direction Register bit 0
.equ DDB1 = 1 ; Port B Data Direction Register bit 1
.equ DDB2 = 2 ; Port B Data Direction Register bit 2
.equ DDB3 = 3 ; Port B Data Direction Register bit 3
.equ DDB4 = 4 ; Port B Data Direction Register bit 4
.equ DDB5 = 5 ; Port B Data Direction Register bit 5
.equ DDB6 = 6 ; Port B Data Direction Register bit 6
.equ DDB7 = 7 ; Port B Data Direction Register bit 7
so it MAY have been there a long time ago but I can't find it.
AND how old is that data sheet? It doesn't show DDRx anything in my datasheet.
I dug through all of my DS's to find the table the OP posted, on the ATMEL Mxx8P DS the DDR bits are named DDBn, but on the ATMEL M328PB DS, it shows DDRBn !!!
So the question is what DS is the OP looking at? Is this an Atmel ds to MC ds change? How are the bits named for other AVR micros?
#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."
The only error is the 3 instead of 2 cycles. I think their use of the word "jump" is just in the general sense meaning "some opcode that gets you from one place to another". Both JMP and RJMP achieve that. I agree that if they'd said "The vector is normally a JMP to the interrupt routine, and this jump takes three clock cycles. " then that would be wrong. (obviously the 3 cycle thing is an error though).
- Log in or register to post comments
TopDevice: ATtiny167
Datasheet Revision: 8265C-AVR-03/12
Feature: Dynamic Clock Switch
The code section in datasheet page 34 (non-watchdog) & page 36 (with watchdog) has a missing section of code & the CLOCK_AVAILABILITY definition.
The missing definition to be added:
The missing section of code:
Without the above section of code & definition, the CLKRDY bit in CLKCSR will NEVER be set thereby putting your code in endless loop in:
Atmel support has confirmed this error & the above missing section of code was provided by them.
My complete & tested code is below:
Once an engineer, forever an engineer
- Log in or register to post comments
TopThanks for sharing, it is now saved in my bottomless pit of AVR stuff. :-)
John Samperi
Ampertronics Pty. Ltd.
https://www.ampertronics.com.au
* Electronic Design * Custom Products * Contract Assembly
- Log in or register to post comments
TopATmega644(P) and ATmega1284(P):
High slewrate data on RxD0 disturbs the crystal oscillator in the AVR when it's not set to "Full swing" with the fusebits.
So either reduce the slewrate on RxD (using 10k - 100pF Low pass filter), or set the oscillator to full swing.
All credits to njepsen on the MCSelec-forum
http://www.mcselec.com/index2.ph...
I am just the messenger ;)
Nard
Dragon broken ? http://aplomb.nl/TechStuff/Dragon/Dragon.html for how-to-fix tips
- Log in or register to post comments
TopAtmega48A/88A/168A/328A+PA datasheet
doc: 8271G-AVR-02/2013
In section 20.7 there is a bug in the example
The assembly example is:
Here the USART Data register Empty flag is checked instead of the USART Receive Complete flag.
The fun part is that the C code example below that does have the correct code:
- Log in or register to post comments
TopAT90CAN128: aborting a pending MOb can leave CONMOB in an unexpected state
I am not sure what kind of bug this is: could be a hardware bug or could be Atmel's library at90CANlib_3_2 being buggy AND misleading.
The library's procedure to abort a MOb that was pending consists on writing 0 to the CONMOB bits. Also, the library depends on those bits being 0 to detect a MOb as being free.
Turns out that a failed MOb (e.g. because of bus errors) will retry its process, and if its CONMOB is overwritten with 0 in that situation there is a rare chance that the CONMOB will jump back to its old value. So any routine testing for CONMOB==0 will consider the MOb busy. Result: a MOb leaked and unusable until reset.
I wrote Atmel about this and their answer was that:
... but that is not a good solution, because ABRQ aborts all MObs. I only wanted to abort one MOb.
Also they said, ...
Which is true according to the documentation, which mentions that CANEN is the register to check for availability of MObs. But that means that the library is pretty b0rked, since it never even refers to the CANEN registers.
Also, the manual mentions repeatedly that the CONMOB is not expected to change by itself, not even after a reset. Which makes me think that this is actually a hardware bug (no?).
Anyway, my minimal workaround is: when aborting a MOb, write 0 to CONMOB, check that the corresponding CANEN bit is 0, and rewrite the 0 to CONMOB.
Alternatively, to search for free MObs, stop checking CONMOB and switch to checking CANEN.
- Log in or register to post comments
TopATtiny13A datasheet 8126F-AVR-05/12 chapter 7.5.1.
BODCR - BOD Control Register bitnames are labeled as BODS and BODSE, while in the tn13Adef.inc are labeled as BPDS and BPDSE.
RES
- Log in or register to post comments
TopTypo in t25/45/85 datasheet, page 150, table 20-7. The rightmost column should read "Signature Byte 2" instead of 0.
I have no special talents. I am only passionately curious. - Albert Einstein
- Log in or register to post comments
TopThe low power oscillator itself is a bug imho. I have seen it cause all manner of glitchy, impossible to debug problems, which are magically cured by going back to the full swing oscillator.
- Log in or register to post comments
TopTwo typing errors in ATmega64M1 datasheet (7647K–AVR–12/13 )
19.2.2 Current Source for Low Cost Traducer
An external transducer based on variable resistor can be connected to the current source. This ca be for instance:
● A thermistor, or temperature-sensitive resistor, used as a temperature sensor
● A CdS photoconductive cell, or luminosity-sensitivity resistor, used as a luminosity sensor.
Using the current source with this type of transducer eliminates the need for additional parts otherwise required in resistor
network or Wheatstone bridge.
RES
- Log in or register to post comments
TopMany AVR8 datasheets, including modern versions for e.g. Mega48 family and Mega164 family, have the "I/O pin input hysteresis vs. VCC" graph in Typical Characteristics scaled in millivolts (mV). It should be volts (V), as in e.g. Tiny1634 sheet.
You can put lipstick on a pig, but it is still a pig.
I've never met a pig I didn't like, as long as you have some salt and pepper.
- Log in or register to post comments
TopATtiny4/5/9/10 datasheet.
link: http://www.atmel.com/images/atme...
page 146, section 16.4.2
SST - Serial STore to data space using indirect addressing
This binary value is wrong....
"DS[PR] ← data 0110 0000 PR ← PR + 1 Post increment"
It should be...
"DS[PR] ← data 0110 0100 PR ← PR + 1 Post increment"
- Log in or register to post comments
TopDevice: MEGA644P family
Summary: Datasheet errata
Datasheet assembler examples (notably the USART) do not appear to have been updated to reflect that some registers are now outside the 'magic 32' where in and out instructions work and therefore lds and sts need to be sued, and the example code will throw errors.
It's me again...
- Log in or register to post comments
TopThank you.
Note that the 'magic 32' are for the single-instruction bit-manipulation and bit-testing instructions like SBI/CBI/SBIS/SBIC. Instructions like IN/OUT will work on all 64 I/O registers.
"Experience is what enables you to recognise a mistake the second time you make it."
"Good judgement comes from experience. Experience comes from bad judgement."
"Wisdom is always wont to arrive late, and to be a little approximate on first possession."
"When you hear hoofbeats, think horses, not unicorns."
"Fast. Cheap. Good. Pick two."
"We see a lot of arses on handlebars around here." - [J Ekdahl]
- Log in or register to post comments
Topstub does your datasheet contain a little note at the bottom of the examples which says:
which in turn says
Anyway assembler tragics use macros to overcome that sort comings
AVR001: Conditional Assembly and portability macros
John Samperi
Ampertronics Pty. Ltd.
https://www.ampertronics.com.au
* Electronic Design * Custom Products * Contract Assembly
- Log in or register to post comments
TopDevice: XMEGA128A1U
Summary: Analog Comparator silicon errata
The XMEGA128A1U (and probably XMEGA64A1U) does not make AC1OUT signals available on PA6 and PB6.
Not a problem if just migrating from older XMEGA128A1 device. Could bite you if migrating from a different AU device (A4U in my case).
Workaround: AC ISR to toggle output pin if you can tolerate the latency.
- Log in or register to post comments
TopThe event system can route an event sourced by AC to be sunk by a port pin.
Edit : manual
"Dare to be naïve." - Buckminster Fuller
- Log in or register to post comments
TopDevice: ATmega328PB datasheet (complete) 40001906A, (C) 2017
Summary: PD0 incorrectly listed as RXD1 (USART1 Input Pin) on page 98 under "17.3.3. Alternate Functions of Port D". Correct assignment for PD0 is RXD0 (USART0 Input Pin) as elsewhere in datasheet (including "Table 6-1. PORT Function Multiplexing"). Also makes ATmega328PB Xplained Mini schematic more logical: unlikely to use USART0 for TXD and USART1 for RXD.
- Log in or register to post comments
TopDevice: ATmega328PB Xplained Mini User Guide 42469B, updated 2015-08
Summary: PD1 and PD0 ATmega328PB pins incorrectly swapped in "Table 2-10 J104 USART Header" on p.17. (ATmega328PB Xplained Mini schematic A09-2523 Rev. 4, 04.01.2017, is correct.)
- Log in or register to post comments
TopThe latest (0856L - Nov '16) revision of the Atmel AVR Instruction Set Manual gives the mistaken impression that an intermediary register will often be needed with the EOR instruction. In section 58.1 (p91), among the operands, the bitmask register Rr is restricted to R0 - R3. You can't use LDI to load a bitmask register with that restriction: LDI requires R16 - R31.
The problem is a typo - a missing '1': the restriction on Rr should be R0 - R31. This is hinted at by the example (in 58.2 on the same page) which uses R4 for Rr; that would be wrong if the limit of R3 were correct. More significant, the opcode shows five bits for Rr (R0 - R31) not two as it would if the limit of R3 were correct.
- Log in or register to post comments
TopAVR910: In-System Programming APPLICATION NOTE
The document states that Programming Enable command ($AC 53 xx yy) gets reply ($zz AC 53 xx).
That is not correct. It does not echo AC in the second byte of the reply.
- Log in or register to post comments
TopIt should. It's usually the input delayed by one byte.
- Log in or register to post comments
TopNote that the command in question is "Programming Enable". The echo-to-MISO likely isn't enabled until programming is enabled. That happens after the $53 is received, so echoing likely starts on the 3rd byte, echoing the second byte, $53.
Note that device datasheets are not definitive, but seem to support this interpretation:
Note that I have not confirmed on hardware what @MASIP has reported above.
"Experience is what enables you to recognise a mistake the second time you make it."
"Good judgement comes from experience. Experience comes from bad judgement."
"Wisdom is always wont to arrive late, and to be a little approximate on first possession."
"When you hear hoofbeats, think horses, not unicorns."
"Fast. Cheap. Good. Pick two."
"We see a lot of arses on handlebars around here." - [J Ekdahl]
- Log in or register to post comments
TopThe latest complete datasheet (DS40001906C, dated 2018-02-22) still gives conflicting pinouts for serial ISP.
"Figure 32-6. Serial Programming and Verify, VCC = 1.8 - 5.5V" on p400 shows MOSI, MISO and SCK as PB5, PB6 and PB7 respectively. That's wrong; it appears to be copied from the datasheet for the ATmega324PB (for which those pins are correct).
For the ATmega328PB the correct pins for MOSI, MISO and SCK are PB3, PB4 and PB5 respectively. The datasheet has that correct further down the page, in "Table 32-15. Pin Mapping Serial Programming". (The schematic for the 328PB Xplained Mini board also shows the correct pins.)
Below Table 32-15 there also appears this confusing note: "The pin mapping for SPI programming is listed. Not all parts use the SPI pins dedicated for the internal SPI interface." What it means is this: The pin mapping for serial ISP is listed. There are pins dedicated for the internal SPI but not all parts use them for ISP.
- Log in or register to post comments
TopI believe there an error in the ATmega48A.../328/P datasheet, dated 2018, DS40002061A.
On page 131, Section 16.9.1, the second paragraph starting "The Input Capture ..." states the need to deal with "resolution of the counter", but I think they mean "range of the counter".
Edit: Or am I missing something with respect to the term "resolution"?
- Log in or register to post comments
TopThis appears to be what is meant by "resolution."
See sections 15.7.1 and 15.7.2 on page 107.
--Mike
- Log in or register to post comments
TopDevice: ATtiny212/ATtiny412
Summary: Wrong mux table in the datasheet
Datasheet: Rev. A - 01/2017
Here is the right mux table:
- Log in or register to post comments
TopDevice: ATmega32U4
Summary: Errors in datasheet 7766J (04/2016), Chapter 32 "Instruction Set Summary"
I've tested the CALL and RET instructions, and their #Clocks values are wrong.
Since the Program Counter (PC) is 16 bits wide:
- the CALL instruction pushes 2 bytes on the stack,
- the CALL instruction takes only 4 cycles -- instead of 5,
- the RET instruction takes only 4 cycles -- instead of 5.
Since the wrong values might come from the copy of data corresponding to a device with a larger memory space, the values for the RCALL, ICALL, EICALL and RETI instructions should also be checked.
- Log in or register to post comments
TopATTINY1614
Datasheet says on pg337; "When the USART is set in one-wire mode, the transmitter and the receiver share the same RxD I/O pin."; (that is wrong)
One-Wire pin is the TXD pin, NOT THE RXD PIN
Microchip has confirmed that TXD is the correct pin for One-Wire. I'm in the process of trying to get Microchip to update the datasheet.
Also not specified in the datasheet for One-Wire mode...
If TX pin is set as output, ODME "Open Drain Mode Enable" does not work.
so TX port must NOT be set as output when using ODME "Open Drain Mode Enable".
This is Not specified in the datasheet.
The following statement from pg340 about one wire setup is vague.
For setting the USART in One-Wire mode, the following initialization sequence is recommended:
1) Set the TxD/RxD pin value high, and optionally set the XCK pin low.
*Needs clarification, what does "Set the TxD pin value high" mean, pullup resistors? or set as output?
*testing shows that in open drain mode, pin should NOT be set as output
2) Optionally, write the ODME bit in the USARTn.CTRLB register to '1' for Wired-AND functionality.
3) Set the TxD/RxD and optionally the XCK pin as an output.
4) Select the baud rate and frame format.
5) Select the mode of operation (enables XCK pin output in Synchronous mode).
6) Enable the transmitter or the receiver, depending on the usage
Tested and working method for 1 wire.
1) Do NOT set TxD pin as output
2) Enable Pullup Resistor on TxD pin if NOT using external pullup.
3) set bit LBME "Loop-back Mode Enable"
4) set bit ODME "Open Drain Mode Enable"
5) Use TxD pin for Transmit and Receive operations.
6) Enable the transmitter or the receiver, depending on the usage
- Log in or register to post comments
TopPlease also publish this in a separate Tiny1614 thread because nobody who needs it (maybe including me) will ever find it here when the time comes.
Jim
Until Black Lives Matter, we do not have "All Lives Matter"!
- Log in or register to post comments
Topgot it done, https://www.avrfreaks.net/forum/attiny1614-one-wire-errata-datasheet-errors
- Log in or register to post comments
TopNew silicon errata found on ATMEGA324PB: OC1B signal on pin PD4 stops working if USART1 is enabled.
Case 00496661 submitted to Microchip.
This is really annoying, because in my design I can't use my second stepper motor (step signal connected to OC1B) together with the second UART. (I Use 2 steppers and 2 UART's, so I cannot use other channels).
Here is a minimal code example to demonstrate the bug.
- Log in or register to post comments
Top--- USI SPI Compliance ---
The AVR Universal Serial Interface (USI) Three-wire external clock modes are compliant with SPI modes 1 and 3. The datasheet (e.g., ATtiny84A) partially correctly states that the "USI clock modes correspond to SPI data modes 0 and 1". However, the datasheet USI Three-wire Mode Timing Diagram figure and supporting text are ambiguous and/or fundamentally incorrect with regards to how the USI actually functions; most importantly, the described clock edge phase association with DI-sample/DO-change events are either inconsistent or wrong.
I have notified Microchip, who said they are looking into it.
The following figure summarizes the USI external clock modes functionality:
The following ATtiny84A program characterizes the USI DI-sample/DO-change timing on a standalone chip without need for an oscilloscope to observe results (although a scope is very useful):
#include <avr/io.h> #include <avr/interrupt.h> #include <avr/cpufunc.h> #include <util/delay.h> #include <stdint.h> #include <stdbool.h> // Purpose: // Discover USI Three-wire external clock mode DI and DO timing wrt USCK // without external connections to device pins (self-acquisition). // Results summary (USICS1 = 1): // USICS0 = 0 with normally high USCK: This USI usage mode looks the same as SPI mode 3 (CPOL=1, CPHA=1) // USICS0 = 1 with normally low USCK: This USI usage mode looks the same as SPI mode 1 (CPOL=0, CPHA=1) // USICS0 = 0 with normally low USCK: This USI usage mode does not look any SPI mode // USICS0 = 1 with normally high USCK: This USI usage mode does not look any SPI mode // Method: // 1. Manually generate 16 USCK edges for each simulated transfer. // 2. Use Pin Change interrupts for DO and USCK to capture time, pin state, and USICNT for each pin state change. // 3. Apply simulated DI pin input, then capture the time when it is sampled by the USI for each Data register bit. // Detailed observations for all combinations of USICS0 and normal USCK clock states: #define USICS0_VALUE 0 // USI clock source edge select (0 or 1): 0=="positive edge", 1=="negative edge" #define NORMAL_USCK_STATE 1 // USI USCK normal (before and after transfer) state (0 or 1): 0==low, 1==high // USICS0 = 0 with normally high USCK (This USI usage mode looks the same as SPI mode 3 (CPOL=1, CPHA=1)): // DO is changed on leading (falling) USCK edges 1(MSB),3(b6),5(b5),7(b4),9(b3),11(b2),13(b1),15(LSB); (not changed at write to USIDR) // DI is sampled on trailing (rising) USCK edges 2(MSB),4(b6),6(b5),8(b4),10(b3),12(b2),14(b1),16(LSB) //#define USICS0_VALUE 1 // USI clock source edge select (0 or 1): 0=="positive edge", 1=="negative edge" //#define NORMAL_USCK_STATE 0 // USI USCK normal (before and after transfer) state (0 or 1): 0==low, 1==high // USICS0 = 1 with normally low USCK (This USI usage mode looks the same as SPI mode 1 (CPOL=0, CPHA=1)): // DO is changed on leading (rising) USCK edges 1(MSB),3(b6),5(b5),7(b4),9(b3),11(b2),13(b1),15(LSB); (not changed at write to USIDR) // DI is sampled on trailing (falling) USCK edges 2(MSB),4(b6),6(b5),8(b4),10(b3),12(b2),14(b1),16(LSB) // MSB is sampled (DI) on 2nd USCK edge (USICNT=1 to 2); LSB is sampled (DI) on 16th USCK edge (USICNT=15 to 0) //#define USICS0_VALUE 0 // USI clock source edge select (0 or 1): 0=="positive edge", 1=="negative edge" //#define NORMAL_USCK_STATE 0 // USI USCK normal (before and after transfer) state (0 or 1): 0==low, 1==high // USICS0 = 0 with normally low USCK (This USI usage mode does not look any SPI mode): // DO is changed to MSB at write to USIDR, // then on trailing (falling) USCK edges 2(b6),4(b5),6(b4),8(b3),10(b2),12(b1),14(LSB),16(next MSB) // DI is sampled on mixed USCK edges; rising 3(MSB),5(b6),7(b5),9(b4),11(b3),13(b2),15(b1), and falling 16(LSB) //#define USICS0_VALUE 1 // USI clock source edge select (0 or 1): 0=="positive edge", 1=="negative edge" //#define NORMAL_USCK_STATE 1 // USI USCK normal (before and after transfer) state (0 or 1): 0==low, 1==high // USICS0 = 1 with normally high USCK (This USI usage mode does not look any SPI mode): // DO is changed to MSB at write to USIDR, // then on trailing (rising) USCK edges 2(b6),4(b5),6(b4),8(b3),10(b2),12(b1),14(LSB),16(next MSB) // DI is sampled on mixed USCK edges; falling 3(MSB),5(b6),7(b5),9(b4),11(b3),13(b2),15(b1), and rising 16(LSB) // Hardware abstraction for bit access: struct bits { uint8_t b0:1; uint8_t b1:1; uint8_t b2:1; uint8_t b3:1; uint8_t b4:1; uint8_t b5:1; uint8_t b6:1; uint8_t b7:1; } __attribute__((__packed__)); #define BIT(portLetter, bitNumber, registerName) ((*(volatile struct bits*)®isterName##portLetter).b##bitNumber) // portLetter = A-D, bitNumber = 0-7, registerName = "PORT", "PIN", or "DDR" #define INPUT 0 // DDR bit = input #define OUTPUT 1 // DDR bit = output // Pin usage map: // ATtiny84A Port Functions // Name Num FuncA FuncB FuncC FuncD FuncE FuncF Usage // ---- --- ----- ----- ----- ----- ----- ----- ----- // PA7 6 ADC7 OC0B ICP1 - - PCINT7 == // PA6 7 ADC6 DI SDA MOSI OC1A PCINT6 == USI DI // PA5 8 ADC5 DO MISO OC1B - PCINT5 == USI DO, PCINT5 // PA4 9 ADC4 USCK SCL T1 - PCINT4 == USI USCK, PCINT4 // PA3 10 ADC3 T0 - - - PCINT3 == // PA2 11 ADC2 AIN1 - - - PCINT2 == // PA1 12 ADC1 AIN0 - - - PCINT1 == // PA0 13 ADC0 AREF - - - PCINT0 == scope trigger // // PB3 4 RESET dW - - - PCINT11 == dW // PB2 5 INT0 OC0A CKOUT - - PCINT10 == // PB1 3 XTAL2 - - - - PCINT9 == resonator // PB0 2 XTAL1 CLKI - - - PCINT8 == resonator // // Vcc 1 // GND 14 // Pin assignments #define USI_DI(r) BIT(A, 6, r) // USI 3-wire mode DI #define USI_DO(r) BIT(A, 5, r) // USI 3-wire mode DO #define USI_USCK(r) BIT(A, 4, r) // USI 3-wire mode USCK #define SCOPE_TRIG(r) BIT(A, 0, r) // scope trigger #define PCINT_DO PCINT5 // DO pin change interrupt mask bit #define PCINT_USCK PCINT4 // USCK pin change interrupt mask bit // Constants const double timeTick = 40e-6; // time clock tick length (sec) #define nEdges 16 // USCK edges per transfer #define nBits 8 // data bits per transfer const uint8_t endOfTime = 255; // time stops here const uint8_t delayUsck = 10; // delay before first USCK edge (use 10 to "tag" 1st edge for capture readability) const uint8_t usckWidth = 10; // half of USCK period (use 10 to "tag" edges in multiples of 10 for capture readability) const uint8_t txData = 0xaa; // DO transmit data--need alternating bit values to force DO change at each update const double delayTransfer = 2 * usckWidth * timeTick; // delay between transfers (sec) // RAM variables volatile uint8_t time; // runs from 0 to 255 * timeTick seconds volatile uint8_t tNextEdge; // scheduled time for USCK edge output change volatile uint8_t pinChangeCount; // DO/USCK pin change counter (pin change capture buffer index) volatile uint8_t captureTimeUsck[nEdges]; // capture buffer for time of USCK pin change volatile uint8_t captureStateUsck[nEdges]; // capture buffer for USCK pin state at pin change volatile uint8_t captureUsicntUsck[nEdges]; // capture buffer for USICNT at USCK pin change volatile uint8_t captureTimeDo[nEdges]; // capture buffer for time of DO pin change volatile uint8_t captureStateDo[nEdges]; // capture buffer for DO pin state at pin change volatile uint8_t captureUsicntDo[nEdges]; // capture buffer for USICNT at DO pin change volatile uint8_t captureTimeDi[nBits]; // capture buffer for time of DI pin sample==1 for each USI Data Register Rx bit volatile uint8_t delayDi; // DI pin stimulus (pin state set to 1) delay volatile uint8_t bitDi; // DI capture bit number (DI capture buffer index) static inline void Break(void) { asm volatile("break\n\t"::); // breakpoint instruction } ISR(PCINT0_vect) { // USI DO and USCK pin change interrupt (handle only one at a time) if ( PCMSK0 & (1<<PCINT_DO) ) { captureStateDo[pinChangeCount] = USI_DO(PIN); // capture DO pin state captureTimeDo[pinChangeCount] = time; // absolute timestamp (includes delayUsck) captureUsicntDo[pinChangeCount] = USISR & ((1<<USICNT3) | (1<<USICNT2) | (1<<USICNT1) | (1<<USICNT0) ); // capture USI USCK edge counter } else if ( PCMSK0 & (1<<PCINT_USCK) ) { captureStateUsck[pinChangeCount] = USI_USCK(PIN); // capture USCK pin state captureTimeUsck[pinChangeCount] = time; // absolute timestamp (includes delayUsck) captureUsicntUsck[pinChangeCount] = USISR & ((1<<USICNT3) | (1<<USICNT2) | (1<<USICNT1) | (1<<USICNT0) ); // capture USI USCK edge counter } if ( pinChangeCount < nEdges ) { pinChangeCount++; } } ISR(TIM0_COMPA_vect, ISR_NOBLOCK) // non-blocking to allow USI DO pin change ISR { // Time clock tick service // DI stimulus if ( time == delayDi ) { USI_DI(PORT) = 1; // set USI DI pin _NOP(); _NOP(); // ensure sample setup time (input synchronizer delay) is met in case USCK edge is scheduled for same time } // USCK generator if ( (USISR & (1<<USIOIF)) == 0 ) { if ( time == tNextEdge ) // time for next edge? { USI_USCK(PIN) = 1; // toggle USCK pin tNextEdge = time + usckWidth; // schedule next edge } } // If no more time, then stop time clock if ( time == endOfTime ) { TIMSK0 = 0; } time++; } void RunTransferClockAndDiStim( void ) { USI_DI(PORT) = 1; // scope trigger USI_DI(PORT) = 0; // clear USI DI pin USIDR = txData; // at USIDR write: if USCK(pin) == USICS0_VALUE, then DO is changed to MSB, else DO unchanged _delay_us( delayTransfer * 1e6 ); cli(); time = 0; // reset time tNextEdge = delayUsck; // schedule first USCK edge USISR = 1<<USIOIF; // clear USI USCK edge counter overflow flag, and reset count TIMSK0 = 1<<OCIE0A; // enable time interrupt; start transfer sei(); while ( (TIMSK0 & (1<<OCIE0A)) != 0 ); // wait until ISR stops time clock } int main(void) { uint8_t i; USI_DI(DDR) = OUTPUT; USI_DO(DDR) = OUTPUT; USI_USCK(DDR) = OUTPUT; SCOPE_TRIG(DDR) = OUTPUT; USI_USCK(PORT) = NORMAL_USCK_STATE; // when does this need to occur wrt USISR, USICR? SCOPE_TRIG(PORT) = 0; _delay_us( 10 * delayTransfer * 1e6 ); // Configure Timer/Counter 0 (8-bit) for use as time clock // Mode 2, Clear Timer on Capture (CTC), TOP = OCR0A TCCR0A = 2<<WGM00 | 0<<COM0A0; // non-PWM, OC0A/OC0B disconnected //TCCR0B = 1<<CS00; // 1x prescale //TCCR0B = 2<<CS00; // 8x prescale TCCR0B = 3<<CS00; // 64x prescale //TCCR0B = 4<<CS00; // 256x prescale //TCCR0B = 5<<CS00; // 1024x prescale OCR0A = ((timeTick)*F_CPU)/64 - 1; //TIMSK0 = 1<<OCIE0A; // enable time interrupt USICR = (1<<USIWM0) | (1<<USICS1) | (USICS0_VALUE<<USICS0); // USI mode = 3-wire; clock source = external // Pre-fill capture buffers with invalid data that indicates non-capture for ( i = 0; i < nEdges; i++ ) { captureTimeUsck[i] = 0; captureStateUsck[i] = 255; captureUsicntUsck[i] = 255; captureTimeDo[i] = 0; captureStateDo[i] = 255; captureUsicntDo[i] = 255; } sei(); GIMSK = 1<<PCIE0; // Discover USCK change timing/selftest (only need single transfer) pinChangeCount = 0; PCMSK0 = 1<<PCINT_USCK; // enable only USI USCK pin change interrupt RunTransferClockAndDiStim(); // let pin change ISR capture USCK change timing // Discover DO update (USI Data Register shifted out) timing (only need single transfer) pinChangeCount = 0; PCMSK0 = 1<<PCINT_DO; // enable only USI DO pin change interrupt RunTransferClockAndDiStim(); // let pin change ISR capture DO update timing GIMSK = 0; // disable external interrupts // Discover DI sample timing for each USI Data Register bit shifted in delayDi = endOfTime; // set DI delay sweep to initial value (sweep from after last (LSB) down to first (MSB) bit) for ( bitDi = 0; bitDi < nBits; bitDi++ ) // watch for last bit shifted in (LSB) first { do { RunTransferClockAndDiStim(); // let time clock ISR stimulate DI at time==delayDi if ( USIBR & (1<<bitDi) ) // did this bit detect DI stimulus in this transfer? { captureTimeDi[bitDi] = delayDi; // yes, capture DI delay timestamp (absolute, includes delayUsck) SCOPE_TRIG(PORT) = 1; SCOPE_TRIG(PORT) = 0; break; // skip to next bit, starting with capture delay of this bit } else { delayDi--; // no, try next DI stimulus delay for this bit } } while ( delayDi >= 0 ); // should never get to delayDi==0 (should detect MSB before) } Break(); }
The following ATmega328P SPI master and ATtiny84A USI Three-wire mode slave programs demonstrate which USI external clock modes are compliant with SPI modes, and which are not:
ATmega328P SPI master code:
#include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> #include <stdint.h> // Test data transfer exerciser using SPI in Master mode #define SPI_MODE_CPOL_CPHA 0 // clock polarity and phase, [CPOL:CPHA] = 0, 1, 2, or 3 // SPI mode 0 (CPOL=0, CPHA=0): SCK idle low; read MISO on SCK lead (rise); write MOSI on SCK trail (fall) or half SCK cycle before 1st lead (rise); MOSI normally high (regardless of last bit) // SPI mode 2 (CPOL=1, CPHA=0): SCK idle high; read MISO on SCK lead (fall); write MOSI on SCK trail (rise) or half SCK cycle before 1st lead (rise); MOSI normally high (regardless of last bit) // SPI mode 1 (CPOL=0, CPHA=1): SCK idle low; read MISO on SCK trail (fall); write MOSI on SCK lead (rise); MOSI normally same as last bit // SPI mode 3 (CPOL=1, CPHA=1): SCK idle high; read MISO on SCK trail (rise); write MOSI on SCK lead (fall); MOSI normally same as last bit // Hardware abstraction for bit access: struct bits { uint8_t b0:1; uint8_t b1:1; uint8_t b2:1; uint8_t b3:1; uint8_t b4:1; uint8_t b5:1; uint8_t b6:1; uint8_t b7:1; } __attribute__((__packed__)); #define BIT(portLetter, bitNumber, registerName) ((*(volatile struct bits*)®isterName##portLetter).b##bitNumber) // portLetter = A-D, bitNumber = 0-7, registerName = "PORT", "PIN", or "DDR" #define INPUT 0 // DDR bit = input #define OUTPUT 1 // DDR bit = output // ATmega328P pin assignments #define SPI_SS_(r) BIT(B, 2, r) // SPI slave select -- output to slave #define SPI_MOSI(r) BIT(B, 3, r) // SPI MOSI -- output to slave #define SPI_MISO(r) BIT(B, 4, r) // SPI MISO -- input from slave #define SPI_SCK(r) BIT(B, 5, r) // SPI SCK -- output to slave #define ERROR_LED_(r) BIT(D, 1, r) // transfer integrity error indicator (note: active-low) const double WAIT_SLAVE_SELECT = 2.0e-6; // wait time (seconds) for slave to prepare for transfer after select const double WAIT_SLAVE_DESELECT = 1.0e-6; // wait time (seconds) for slave to process Tx data after deselect const uint8_t TX_ONLY_MSB_AND_LSB = 0x81; // Tx only MSB and LSB to highlight failure mode and for better trace readability static uint8_t txData; static uint8_t rxData; int main(void) { cli(); SPI_MISO(DDR) = INPUT; SPI_SS_(DDR) = OUTPUT; SPI_MOSI(DDR) = OUTPUT; SPI_SCK(DDR) = OUTPUT; ERROR_LED_(DDR) = OUTPUT; SPCR = (0<<SPIE) | (1<<SPE) | (0<<DORD) | (1<<MSTR) | ((SPI_MODE_CPOL_CPHA) << CPHA); // master, MSB-first //SPCR |= 0<<SPR0; SPSR = 1<<SPI2X; // Fsck = Fclk/2 //SPCR |= 0<<SPR0; // Fsck = Fclk/4 //SPCR |= 1<<SPR0; SPSR = 1<<SPI2X; // Fsck = Fclk/8 SPCR |= 1<<SPR0; // Fsck = Fclk/16 //SPCR |= 2<<SPR0; SPSR = 1<<SPI2X; // Fsck = Fclk/32 //SPCR |= 2<<SPR0; // Fsck = Fclk/64 //SPCR |= 3<<SPR0; SPSR = 1<<SPI2X; // Fsck = Fclk/64 //SPCR |= 3<<SPR0; // Fsck = Fclk/128 ERROR_LED_(PORT) = 1; // (note: active-low error indicator) SPI_SS_(PORT) = 1; // deselect slave // To see failure on scope, trigger on ERROR_LED_ or SPI_SS_ positive-pulse-width-greater-than non-error condition width // To see success on scope, trigger on SPI_SS_ positive-pulse-width-less-than error condition width // Repeatedly transmit same (fixed) data; expect exact data (echo) received from slave // after data pipeline fills/flushes on first transfer. txData = TX_ONLY_MSB_AND_LSB; while ( 1 ) { SPI_SS_(PORT) = 0; // select slave _delay_us( WAIT_SLAVE_SELECT * 1.0e6 ); // wait for slave to prepare for transfer SPDR = txData; // start transfer with Tx data while ( (SPSR & (1<<SPIF)) == 0 ); // wait for transfer to finish rxData = SPDR; // get Rx data SPI_SS_(PORT) = 1; // deselect slave _delay_us( WAIT_SLAVE_DESELECT * 1.0e6 ); // wait for slave to process Tx data if ( rxData != txData ) // check Rx data integrity -- expect echo of previous Tx data { ERROR_LED_(PORT) = 0; // Extend SPI_SS_=1 width for scope trigger on pulse-width-greater-than non-error condition width _delay_us( 2.0 * WAIT_SLAVE_DESELECT * 1.0e6 ); ERROR_LED_(PORT) = 1; } } }
ATtiny84A USI Three-wire mode slave code:
#include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> #include <stdint.h> // Echo received test data using slave USI in Three-wire mode, external clock #define USICS0_VALUE 0 // clock source edge select (0 or 1): 0=="positive edge", 1=="negative edge" // Test observations for USI slave (ATtiny84A @20MHz) in both external clock modes, USICS1=1 and USICS0=0/1 // with real SPI master (ATmega328P @16MHz) in modes 0/1/2/3 with Fusck = 1 MHz: // SPI mode 0 (CPOL=0, CPHA=0): SCK idle low; read MISO on SCK lead (rise); write MOSI on SCK trail (fall) or half SCK cycle before 1st lead (rise); MOSI normally high (regardless of last bit) // SPI mode 2 (CPOL=1, CPHA=0): SCK idle high; read MISO on SCK lead (fall); write MOSI on SCK trail (rise) or half SCK cycle before 1st lead (rise); MOSI normally high (regardless of last bit) // SPI mode 1 (CPOL=0, CPHA=1): SCK idle low; read MISO on SCK trail (fall); write MOSI on SCK lead (rise); MOSI normally same as last bit // SPI mode 3 (CPOL=1, CPHA=1): SCK idle high; read MISO on SCK trail (rise); write MOSI on SCK lead (fall); MOSI normally same as last bit // USI slave USICS0=0 / SPI master mode 0 (CPOL=0, CPHA=0): DI=0x81 DO=0x03 (fail) "usitest_00.bmp" // USI slave USICS0=0 / SPI master mode 1 (CPOL=0, CPHA=1): DI=0x81 DO=various (fail) "usitest_01.bmp" // USI slave USICS0=0 / SPI master mode 2 (CPOL=1, CPHA=0): DI=0x81 DO=various (fail) "usitest_02.bmp" // USI slave USICS0=0 / SPI master mode 3 (CPOL=1, CPHA=1): DI=0x81 DO=0x81 (pass) "usitest_03.bmp" // USI slave USICS0=1 / SPI master mode 0 (CPOL=0, CPHA=0): DI=0x81 DO=various (fail) "usitest_10.bmp" // USI slave USICS0=1 / SPI master mode 1 (CPOL=0, CPHA=1): DI=0x81 DO=0x81 (pass) "usitest_11.bmp" // USI slave USICS0=1 / SPI master mode 2 (CPOL=1, CPHA=0): DI=0x81 DO=0x03 (fail) "usitest_12.bmp" // USI slave USICS0=1 / SPI master mode 3 (CPOL=1, CPHA=1): DI=0x81 DO=various (fail) "usitest_13.bmp" // Hardware abstraction for bit access: struct bits { uint8_t b0:1; uint8_t b1:1; uint8_t b2:1; uint8_t b3:1; uint8_t b4:1; uint8_t b5:1; uint8_t b6:1; uint8_t b7:1; } __attribute__((__packed__)); #define BIT(portLetter, bitNumber, registerName) ((*(volatile struct bits*)®isterName##portLetter).b##bitNumber) // portLetter = A-D, bitNumber = 0-7, registerName = "PORT", "PIN", or "DDR" #define INPUT 0 // DDR bit = input #define OUTPUT 1 // DDR bit = output // ATtiny84A pin assignments #define SPI_SS_(r) BIT(A, 7, r) // [Pin# 6] SPI slave select -- input from master #define USI_DI(r) BIT(A, 6, r) // [Pin# 7] SPI MOSI -- input from master #define USI_DO(r) BIT(A, 5, r) // [Pin# 8] SPI MISO -- output to master #define USI_USCK(r) BIT(A, 4, r) // [Pin# 9] SPI SCK -- input from master int main(void) { cli(); SPI_SS_(DDR) = INPUT; USI_DI(DDR) = INPUT; USI_USCK(DDR) = INPUT; USI_DO(DDR) = OUTPUT; USICR = (1<<USIWM0) | (1<<USICS1) | (USICS0_VALUE<<USICS0); // USI mode = 3-wire; clock source = external while( 1 ) { if ( SPI_SS_(PIN) == 1 ) { USI_DO(DDR) = INPUT; // slave is deselected; float DO USISR = 1<<USIOIF; // synch/reset USCK edge counter, and clear overflow flag USIDR = USIBR; // pre-load Tx test data } else { USI_DO(DDR) = OUTPUT; // slave is deselected; drive DO (master waits enough time) if ( USISR & (1<<USIOIF) ) // transfer complete? (master supplies clock) { USISR = 1<<USIOIF; // reset USCK edge counter, and clear overflow flag } } } }
- Log in or register to post comments
TopDevice: atmega324PB
Summary: PCINT on PE pins documentation is wrong and incomplete
Details:
In the datasheet DS40001908A:
* page 427: the register number for PCMSK4 is given as 0x74, but it is really 0x75
* page 16: the PCINT34..PCINT38 functionality on pins PE2..PE6 is missing in the table
* page 104: the PCINT32..PCINT38 functionality on PE is missing in tables 16-15 and 16-16
- Log in or register to post comments
TopI found what I believe is a spelling error in some of the atdf files for the atmega-2.0.12 device pack release.
- Log in or register to post comments
TopThe latest version of the AVR Instruction Set Reference (Rev. 0856F–AVR–05/08) Has a section marked "SPM #2" That shows an additional form of SPM. The shown opcode for forms i-iii ("SPM") cannot be correct as it conflicts with "BCLR 4" (also known as "CLS") get-mobdro.com
- Log in or register to post comments
TopThat is not the latest. I have version 'L' here and I'm not even sure if that is the latest.
#1 Hardware Problem? https://www.avrfreaks.net/forum/...
#2 Hardware Problem? Read AVR042.
#3 All grounds are not created equal
#4 Have you proved your chip is running at xxMHz?
#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."
- Log in or register to post comments
Top[E2A]
The latest version...
#1 Hardware Problem? https://www.avrfreaks.net/forum/...
#2 Hardware Problem? Read AVR042.
#3 All grounds are not created equal
#4 Have you proved your chip is running at xxMHz?
#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."
- Log in or register to post comments
TopFurther effort occurred after the acquisition of Atmel by Microchip Technology (4-Apr'16)
AVR® Instruction Set Manual (Feb'21 PDF)
AVR® Instruction Set Manual (web doc)
"Dare to be naïve." - Buckminster Fuller
- Log in or register to post comments
TopI have DS40002198B and it does not show a conflict that I can see:
BCLR: 1001 0100 1sss 1000
SPM : 1001 0101 1110 1000 (AVRe)
SPM : 1001 0101 1110 1000 (i)-(iv) (AVRxm,AVRxt)
SPM : 1001 0101 1111 1000 (v)-(viii) (AVRxm,AVRxt)
bit 8 differs
- Log in or register to post comments
TopThe way to find out would be to go to the Product Page, and see which version is available there.
It is, in fact, much more recent:
https://ww1.microchip.com/downlo...
Top Tips:
- Log in or register to post comments
TopOriginally posted by FredCailloux at: Error-DDRB-register-bit-names
On page 117 of my ATmega328P datasheet the document clearly show the DDRB register with its corresponding bit names: DDRB7...DDRB0
Yet, when I input a code line in Studio7 , I get an indication that DDRB1 is not a valid constant name.
Also, if I open the DDRB file with "Goto Implementation" feature of Studio7, I find that , indeed, the iom328p.h file open and show the correct name for all DDRB bits are "DDB1"
So, I have to conclude that the Microchip Datasheet for the ATmega328P is wrong.
- Log in or register to post comments
TopAnd I will say that the datasheet is correct and the compiler is wrong!Ok I was wrong, I guess that I never have changed direction on a single IO on the fly.
- Log in or register to post comments
TopThe asm include file for the M328 does not have DDRBx but DDBx
so it MAY have been there a long time ago but I can't find it.
AND how old is that data sheet? It doesn't show DDRx anything in my datasheet.
John Samperi
Ampertronics Pty. Ltd.
https://www.ampertronics.com.au
* Electronic Design * Custom Products * Contract Assembly
- Log in or register to post comments
TopThat's not the case - see the original thread: https://www.avrfreaks.net/commen...
Top Tips:
- Log in or register to post comments
TopI dug through all of my DS's to find the table the OP posted, on the ATMEL Mxx8P DS the DDR bits are named DDBn, but on the ATMEL M328PB DS, it shows DDRBn !!!
So the question is what DS is the OP looking at? Is this an Atmel ds to MC ds change? How are the bits named for other AVR micros?
Jim
FF = PI > S.E.T
- Log in or register to post comments
TopThis is what I see in Microchip branded datasheet from 2020:
- Log in or register to post comments
TopWorth noting that the DDBn nomenclature first appeared in the 1997 data book for the original AVRs.
#1 Hardware Problem? https://www.avrfreaks.net/forum/...
#2 Hardware Problem? Read AVR042.
#3 All grounds are not created equal
#4 Have you proved your chip is running at xxMHz?
#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."
- Log in or register to post comments
TopThat's all it is; just names - neither is "right" nor "wrong": https://www.avrfreaks.net/commen...
Top Tips:
- Log in or register to post comments
TopPages