Help with interrupt only triggering once assembly project atmega 2560 (edited with more legible code)

Go To Last Post
17 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello all. I am desiging a PID controller in assembly for a Microcontrollers final project. It's designed to drive an LTC4440, but for the project I just need to prove to the professor that the PWM output varies with the reading of the ADC (for now. I'd like to get the whole circuit working eventually.) Right now I'm working on just the Proportional part, and I will add the rest later if I get a chance (the P part is what he's really looking for, the rest is optional.)

 

The program I've written uses two timers on the atmega2560 (which is on the arduino mega board), and the ADC. the first timer (timer1) controls the ADC using the ADATE bit and the timer 1 compare B flag. When the ADC is done with its conversion it sets an interrupt (is that the right phrase?)  and converts the value in the ACDCH/L register into a value that changes duty cycle of the PWM, which it then dumps into OCRB3H/L. Timer 3 is the PWM output, which is output on OCR3B.

 

The problem I am having is that while the program works like its supposed to. it only does so once. I use a potentiometer to feed a value between 0 and 5V to the ADC (analog pin 0), and when the program first runs, it correctly reads the ADC and outputs a proportional PWM, but if I change the potentiometer while the program is running, the PWM duty cycle does not change. Currently I need to press the reset button after I change the potentiometer to have the PWM duty cycle change, even though the ADC should be triggering ever 500us based on timer1

 

Here is the code:

;
; AssemblerApplication1.asm
;
; Created: 11/18/2017 2:54:17 PM
; Author : Chris
;

;Definitions
.DEF PWM_OUT = r20
.DEF init1 = r16		;Variables used to initialize registers
.DEF init2 = r17
.DEF init3 = r18
.DEF rmp = r19
.DEF light = r14
.DEF Kp = r21
.DEF VrefL = r22			;Value used to compare with ADC to create E_t
.DEF VrefH = r23
.DEF E_t = r24
.DEF PWMHIGH = r25			;saves the value for PWM cycle so it can be changed
			


.org 0x0000             ;memory (PC) location of reset handler
	rjmp Reset
	
.org 0x0024
	RJMP TIM1_COMPB

.org 0x003A				;memory location for adc ready handler
	RJMP ADC_RDY
                     




;============



Reset:
	LDI VrefH, 0x01					; Value to compare adc to
	LDI VrefL, 0xFF
	LDI PWMHIGH, 160
	LDI Kp, 3
;initialize system clock to 16MHz
	CLI
	LDI init1, (1<<CLKPCE)												;enable CLKPR to allow to change frequency
	LDI init2, (1<<CLKPS0)												;set main prescaler to 8 so it can be seen on cheap oscilliscope
	STS CLKPR, init1
	STS CLKPR, init2
		

;Set up ADC timer (timer 1)
	LDI init1, (1<<COM1A1)												;TCCR1A		CTC mode max = OCR1A
	LDI init2, (1<<WGM12)|(1<<CS10)										;TCCR1B	
	LDI init3, (1<<OCIE1B)												;TIMSK1
	STS TCCR1A, init1
	STS TCCR1B, init2
	STS TIMSK1, init3
	LDI	init1,	0x0F													;countermax = 4000.
	LDI init2,	0xA0													;should trigger every 500us (16Mhz/2/4000)^-1
	STS OCR1BH, init1				
	STS OCR1BL, init2

	;Set up ADC
	LDI	init1, (1<<ADC0D)												;should set ADC port to input	
	STS DIDR0, init1
	LDI init1, (1<<REFS0)												;ADMUX		Vcc reference, ADC input on ADC0 -A0
	LDI init2, (1<<ADTS2)|(1<<ADTS0)									;ADCSRB		Auto trigger on timer1 comp b
	LDI init3, (1<<ADEN)|(1<<ADSC)|(1<<ADATE)|(1<<ADIE)|(1<<ADPS1)|(1<<ADPS0)				;ADCSRA		interrupt enable, prescaler 2
	STS ADMUX, init1			
	STS ADCSRB, init2			
	STS ADCSRA, init3	

;Initial setup of the PWM signal (timer 3)
	LDI	init1,(1<<COM3B1)|(1<<WGM31)|(1<<WGM30) 						;		TCCR3A
	LDI	init2, (1<<WGM33)|(1<<WGM32)|(0<<CS32)|(1<<CS31)|(1<<CS30)		;		TCCR3B
	STS	TCCR3A, init1
	STS	TCCR3B, init2 
	LDI init1, 0														;turn on Interrupt for	TIMSK3
	LDI init2, 0x00														;Max value of PWM (can use 1+2 to make 16-bit)
	MOV	init3, PWMHIGH													; A0 = 160 = 16MHz/100
	STS TIMSK3, init1
	STS ICR3H,	init2
	STS ICR3L,	init3
	LDI init3, 0
	LDI init1, 0
	LDI	init2, 100														;starting value of OCR3B (Duty Cycle OCR3B/OCRA)
	STS OCR3BH, init1
	STS	OCR3AL, init2
	LDI	init1, 0xFF
	OUT	DDRE, init1
	CLR init1
	STS TCNT1H, init1
	STS TCNT1L, init1
	STS TCNT3H, init1
	STS TCNT3L, init1
	SEI                   ; enable global interrupts




;Following code is just a test bed for the pwm code

Start:
	RJMP Start

TIM1_COMPB:
	RETI


ADC_RDY:
	CLR init1						;initialize register for use in compare
	CLR init2
	CLR init3
	CLR r0
	CLR R1
	CLR r2
	CLI								;stop interrupts for 16bit read/write
	LDS init2, ADCL					;AVR uses dst, src instead of src, dst
	LDS init3, ADCH
	PUSH VrefH						;store vref to the stack while we mess with it
	PUSH VrefL
	SUB VrefL, init2				;E(t) = Vref - ADC input
	SBC VrefH, init3				;subtract the upper bytes (with carry)
	MOV	r1, VrefL					;move e(t) into different register to regain Vref values
	MOV r2, VrefH
	POP VrefL						; Reload value of Vref
	POP VrefH
	BRLT Negative					;If e(t) is negative, set PWM value to zero
	CP	r1, init1					
	CPC r2, init1
	BREQ Zero						;If e(t) = 0 don't change anything
	LDI init1, 0xFF					;Check for impossible value from 10bit ADC, saturate high (put back 03FF)
	LDI init2, 0x03
	CP	r1, init1
	CPC r2, init2
	BRSH Too_high
	CALL ADC_Convert				;Convert the 10-bit adc value into a value between 0 - 160
	CALL Round_number
Kp_multiplication:					;multiply value by Kp
	LDS init3, PINC
	ORI init3, 0x02
	MOV r2, r1						;move out of r1, since product is stored in r1:r0
	CLR r0
	CLR r1
	CLR init1
	MUL r2, kp
	CP	r0, PWMHIGH					;check for value higher than PWMHIGH, and saturate if true
	CPC r1, init1 
	BRSH Too_high
	LDS init3, PINC
	ORI init3, 0x12
	MOV PWM_OUT, r0
	RJMP	 calibration_done
Too_high:
	LDS init3, PINC
	ORI init3, 0x01
	MOV PWM_OUT, PWMHIGH
	RJMP Calibration_done
Negative:
	LDS init3, PINC
	ORI init3, 0x04 
	LDI PWM_OUT, 0
	RJMP Calibration_done	
Zero:
	CLR PWM_OUT
	RJMP Calibration_done			;If value is where you want it, don't change anything.
					
Calibration_done:
	LDI init1, 0
	STS OCR3BH, init1
	STS OCR3BL, PWM_OUT
	OUT PORTC, init3
	SEI 
	RETI

ADC_Convert:
; this converts a value from 0-1023 to 0-160 by multiplying by 10,250
; and then dividing by 65,536. the division is accomplished by ignoring
; the last two bytes of the product.
; Have to use subroutine for multiplication, since AVR can only have 
; a result of sixteen bits, and our result can be up to 24 bits
;
; Starting conditions:
; +---+---+
; | R2+ R1|  Input number
; +---+---+
; +---+---+---+---+
; | R6| R5| R4| R3| Multiplicant 10,250 = 0x280A
; | 00| 00| 28| 0A|
; +---+---+---+---+
; +---+---+---+---+
; |R10| R9| R8| R7| Result
; | 00| 00| 00| 00|
; +---+---+---+---+
;

	CLR r6			;set multiplicant
	CLR r5
	LDI rmp, 0x28
	MOV r4, rmp
	LDI rmp, 0x0A
	MOV r3, rmp
	CLR r10
	CLR r9
	CLR r8
	CLR r7
Convert_Start:
	MOV rmp, r1
	OR  rmp, r2		;Check if there are any 1's left
	BRNE Shift_Div
	RET				;No 1's, return to program
Shift_Div:
	LSR r2			;Shift MSB, div by 2			
	ROR r1			;Rotate right through carry on MSP430
	BRCC Skip_Add	;don't add if LSB was 0
	ADD r7, r3		;add #s in r6:r5:r4:r3
	ADC r8, r4
	ADC r9, r5
	ADC r10,r6
Skip_Add:
	LSL r3			;multiply r6::r3 by 2
	ROL r4
	ROL r5
	ROL r6
	RJMP Convert_start ;RJMP saves one cycle. go to next bit

Round_number:			;rounds the number using bit 15
	CLR rmp
	LSL r8				;rotate bit 15 to carry
	ADC r9, rmp			;add the carry to LSbyte
	ADC r10, rmp		;add the new carry to MSbyte
	MOV r2, r10			; do the final division by 65536
	MOV r1, r9
	RET

The fuses (read in atmel studio from an AVR ISP mkii clone) are Extended 0xFD HIGH 0xD8  and LOW 0xFF.

 

The simulation does the same thing, but I think it says that the analog components don't work in simulation, so I thought maybe that's why.

 

Oh, also using atmel studios 7 to write the code. Was using avrdude -cwiring in external tools to download the code, but for some reason that stopped working, so I am downloading straight to the chip with the AVR ISP mkii via atmel studios currently.

 

I have tried to be as thorough as I can, and apologize if I'm forgetting anything obvious. If there's any other information I could provide please do not hesitate to let me know.

 

EDIT: I'm sorry, I just realized I haven't really kept up with the comments in the initialization section, so they aren't correct anymore. My sincerest apologies. I will try to update them ASAP.

 

Everything in the code that has to do with the lights and port C was just test code I was using to see which parts of the program were actually happening. They aren't integral to the program in any way.

 

EDIT2: fixed the control register loading to be more legible thanks to suggestions.

 

Last Edited: Wed. Dec 6, 2017 - 01:16 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There is no way in heck that anyone is going to wade through all those magic numbers to try to debug your code for you.  God gave you bit names.  Use them.

 

As a hunch though, I'd guess you haven't provided an ISR for the ADATE trigger.  A quick look at your value for ADCSRB tells me that you're using TIMER1 COMP B as a trigger source.  The ADC will trigger on the rising edge of that flag.  Unless the flag is cleared either by you in software, or by the hardware when servicing that interrupt, it will stay set and you'll see no additional triggers.

 

Either use an empty ISR for TIMER1 COMP B, or clear OCF1B in TIFR1 in your ADC ISR.

 

Oh heck, I see you're also enabling TIMER1 interrupts OVF, COMP A, and COMP B, but you've only provided an ISR for COMP A... and CAPT for some reason...

 

I assume that the CAPT interrupt and ISR should be COMP B, since the CAPT ISR is empty.

 

In CTC mode, the TIMER1 OVF interrupt will never happen, so the fact that you've enabled that interrupt but not provided an ISR for it won't be a problem... for now.  Until you make a change and wonder why your code goes haywire.  Don't enable any interrupts for which you have not provided an ISR.

 

And for heaven's sake, learn what a magic number is, and never use them again! :)

 

Welcome to AVR Freaks!

 

EDIT:  You're using CTC mode where OCR1A is TOP, but you set OCR1B.

EDIT2:  Many of your comments are still a lie, which is of course worse than no comment at all.

"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]

 

Last Edited: Wed. Dec 6, 2017 - 05:01 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

joeymorin wrote:

There is no way in heck that anyone is going to wade through all those magic numbers to try to debug your code for you.  God gave you bit names.  Use them.

 

As a hunch though, I'd guess you haven't provided an ISR for the ADATE trigger.  A quick look at your value for ADCSRB tells me that you're using TIMER1 COMP B as a trigger source.  The ADC will trigger on the rising edge of that flag.  Unless the flag is cleared either by you in software, or by the hardware when servicing that interrupt, it will stay set and you'll see no additional triggers.

 

Either use an empty ISR for TIMER1 COMP B, or clear OCF1B in TIFR1 in your ADC ISR.

 

Oh heck, I see you're also enabling TIMER1 interrupts OVF, COMP A, and COMP B, but you've only provided an ISR for COMP A... and CAPT for some reason...

 

I assume that the CAPT interrupt and ISR should be COMP B, since the CAPT ISR is empty.

 

In CTC mode, the TIMER1 OVF interrupt will never happen, so the fact that you've enabled that interrupt but not provided an ISR for it won't be a problem... for now.  Until you make a change and wonder why your code goes haywire.  Don't enable any interrupts for which you have not provided an ISR.

 

And for heaven's sake, learn what a magic number is, and never use them again! :)

 

Welcome to AVR Freaks!

 

EDIT:  You're using CTC mode where OCR1A is TOP, but you set OCR1B.

EDIT2:  Many of your comments are still a lie, which is of course worse than no comment at all.

 

Thank you so much for your quick reply. I'm really sorry, I was going by an example I found on how to load registers, but I can see now that it's clearly not best practices. I've updated the code to use the bit names, and fixed some of the problems you mentioned. Do you think you could possibly take another look at it for me? It still doesn't seem to be updating without a reset.

 

;
; AssemblerApplication1.asm
;
; Created: 11/18/2017 2:54:17 PM
; Author : Chris
;

;Definitions
.DEF PWM_OUT = r20
.DEF init1 = r16		;Variables used to initialize registers
.DEF init2 = r17
.DEF init3 = r18
.DEF rmp = r19
.DEF light = r14
.DEF Kp = r21
.DEF VrefL = r22			;Value used to compare with ADC to create E_t
.DEF VrefH = r23
.DEF E_t = r24
.DEF PWMHIGH = r25			;saves the value for PWM cycle so it can be changed
			


.org 0x0000             ;memory (PC) location of reset handler
	rjmp Reset
	
.org 0x0024
	RJMP TIM1_COMPB

.org 0x003A				;memory location for adc ready handler
	RJMP ADC_RDY
                     




;============



Reset:
	LDI VrefH, 0x01					; Value to compare adc to
	LDI VrefL, 0xFF
	LDI PWMHIGH, 160
	LDI Kp, 3
;initialize system clock to 16MHz
	CLI
	LDI init1, (1<<CLKPCE)												;enable CLKPR to allow to change frequency
	LDI init2, (1<<CLKPS0)												;set main prescaler to 8 so it can be seen on cheap oscilliscope
	STS CLKPR, init1
	STS CLKPR, init2
		

;Set up ADC timer (timer 1)
	LDI init1, (1<<COM1A1)												;TCCR1A		CTC mode max = OCR1A
	LDI init2, (1<<WGM12)|(1<<CS10)										;TCCR1B	
	LDI init3, (1<<OCIE1B)												;TIMSK1
	STS TCCR1A, init1
	STS TCCR1B, init2
	STS TIMSK1, init3
	LDI	init1,	0x0F													;countermax = 4000.
	LDI init2,	0xA0													;should trigger every 500us (16Mhz/2/4000)^-1
	STS OCR1BH, init1				
	STS OCR1BL, init2

	;Set up ADC
	LDI	init1, (1<<ADC0D)												;should set ADC port to input	
	STS DIDR0, init1
	LDI init1, (1<<REFS0)												;ADMUX		Vcc reference, ADC input on ADC0 -A0
	LDI init2, (1<<ADTS2)|(1<<ADTS0)									;ADCSRB		Auto trigger on timer1 comp b
	LDI init3, (1<<ADEN)|(1<<ADSC)|(1<<ADATE)|(1<<ADIE)|(1<<ADPS1)|(1<<ADPS0)				;ADCSRA		interrupt enable, prescaler 2
	STS ADMUX, init1			
	STS ADCSRB, init2			
	STS ADCSRA, init3	

;Initial setup of the PWM signal (timer 3)
	LDI	init1,(1<<COM3B1)|(1<<WGM31)|(1<<WGM30) 						;		TCCR3A
	LDI	init2, (1<<WGM33)|(1<<WGM32)|(0<<CS32)|(1<<CS31)|(1<<CS30)		;		TCCR3B
	STS	TCCR3A, init1
	STS	TCCR3B, init2 
	LDI init1, 0														;turn on Interrupt for	TIMSK3
	LDI init2, 0x00														;Max value of PWM (can use 1+2 to make 16-bit)
	MOV	init3, PWMHIGH													; A0 = 160 = 16MHz/100
	STS TIMSK3, init1
	STS ICR3H,	init2
	STS ICR3L,	init3
	LDI init3, 0
	LDI init1, 0
	LDI	init2, 100														;starting value of OCR3B (Duty Cycle OCR3B/OCRA)
	STS OCR3BH, init1
	STS	OCR3AL, init2
	LDI	init1, 0xFF
	OUT	DDRE, init1
	CLR init1
	STS TCNT1H, init1
	STS TCNT1L, init1
	STS TCNT3H, init1
	STS TCNT3L, init1
	SEI                   ; enable global interrupts




;Following code is just a test bed for the pwm code

Start:
	RJMP Start

TIM1_COMPB:
	RETI


ADC_RDY:
	CLR init1						;initialize register for use in compare
	CLR init2
	CLR init3
	CLR r0
	CLR R1
	CLR r2
	CLI								;stop interrupts for 16bit read/write
	LDS init2, ADCL					;AVR uses dst, src instead of src, dst
	LDS init3, ADCH
	PUSH VrefH						;store vref to the stack while we mess with it
	PUSH VrefL
	SUB VrefL, init2				;E(t) = Vref - ADC input
	SBC VrefH, init3				;subtract the upper bytes (with carry)
	MOV	r1, VrefL					;move e(t) into different register to regain Vref values
	MOV r2, VrefH
	POP VrefL						; Reload value of Vref
	POP VrefH
	BRLT Negative					;If e(t) is negative, set PWM value to zero
	CP	r1, init1					
	CPC r2, init1
	BREQ Zero						;If e(t) = 0 don't change anything
	LDI init1, 0xFF					;Check for impossible value from 10bit ADC, saturate high (put back 03FF)
	LDI init2, 0x03
	CP	r1, init1
	CPC r2, init2
	BRSH Too_high
	CALL ADC_Convert				;Convert the 10-bit adc value into a value between 0 - 160
	CALL Round_number
Kp_multiplication:					;multiply value by Kp
	LDS init3, PINC
	ORI init3, 0x02
	MOV r2, r1						;move out of r1, since product is stored in r1:r0
	CLR r0
	CLR r1
	CLR init1
	MUL r2, kp
	CP	r0, PWMHIGH					;check for value higher than PWMHIGH, and saturate if true
	CPC r1, init1 
	BRSH Too_high
	LDS init3, PINC
	ORI init3, 0x12
	MOV PWM_OUT, r0
	RJMP	 calibration_done
Too_high:
	LDS init3, PINC
	ORI init3, 0x01
	MOV PWM_OUT, PWMHIGH
	RJMP Calibration_done
Negative:
	LDS init3, PINC
	ORI init3, 0x04 
	LDI PWM_OUT, 0
	RJMP Calibration_done	
Zero:
	CLR PWM_OUT
	RJMP Calibration_done			;If value is where you want it, don't change anything.
					
Calibration_done:
	LDI init1, 0
	STS OCR3BH, init1
	STS OCR3BL, PWM_OUT
	OUT PORTC, init3
	SEI 
	RETI

ADC_Convert:
; this converts a value from 0-1023 to 0-160 by multiplying by 10,250
; and then dividing by 65,536. the division is accomplished by ignoring
; the last two bytes of the product.
; Have to use subroutine for multiplication, since AVR can only have 
; a result of sixteen bits, and our result can be up to 24 bits
;
; Starting conditions:
; +---+---+
; | R2+ R1|  Input number
; +---+---+
; +---+---+---+---+
; | R6| R5| R4| R3| Multiplicant 10,250 = 0x280A
; | 00| 00| 28| 0A|
; +---+---+---+---+
; +---+---+---+---+
; |R10| R9| R8| R7| Result
; | 00| 00| 00| 00|
; +---+---+---+---+
;

	CLR r6			;set multiplicant
	CLR r5
	LDI rmp, 0x28
	MOV r4, rmp
	LDI rmp, 0x0A
	MOV r3, rmp
	CLR r10
	CLR r9
	CLR r8
	CLR r7
Convert_Start:
	MOV rmp, r1
	OR  rmp, r2		;Check if there are any 1's left
	BRNE Shift_Div
	RET				;No 1's, return to program
Shift_Div:
	LSR r2			;Shift MSB, div by 2			
	ROR r1			;Rotate right through carry on MSP430
	BRCC Skip_Add	;don't add if LSB was 0
	ADD r7, r3		;add #s in r6:r5:r4:r3
	ADC r8, r4
	ADC r9, r5
	ADC r10,r6
Skip_Add:
	LSL r3			;multiply r6::r3 by 2
	ROL r4
	ROL r5
	ROL r6
	RJMP Convert_start ;RJMP saves one cycle. go to next bit

Round_number:			;rounds the number using bit 15
	CLR rmp
	LSL r8				;rotate bit 15 to carry
	ADC r9, rmp			;add the carry to LSbyte
	ADC r10, rmp		;add the new carry to MSbyte
	MOV r2, r10			; do the final division by 65536
	MOV r1, r9
	RET

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

you need to tidy up your comment alignment

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:

you need to tidy up your comment alignment

 

Yeah, it's aligned almost perfect in atmel studio, but not in the post for some reason.

 

Anyway, thank you all for your help. I figured it out. I had timer 1 set to count to OCR1A, but I never put a value in OCR1A. Very stupid >_<

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

cbc02009 wrote:
 it's aligned almost perfect in atmel studio, but not in the post for some reason.

That'll be because you've used TABs.

 

This is the very reason why you should never use TABs - always use spaces.

 

You know where you are with spaces - but TABs are completely at the mercy of the (mis)configuration of each and every individual instance of each and every  different thing that gets used to view them.

 

Any decent programmers editor will have the option to insert spaces when you press the TAB button.

Pretty sure Atmel Studio can also do it.

 

Many programmers editors have a facility to "de-TAB"; ie, convert all existing TABs toappropriate numbers of spaces.

 

#TabsAreEvil #SpacesNotTabs

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I suspect the alignment problem is due to having tab expansion of 4 spaces in studio whereas here they expand to 8.

 

Some would say always set the IDE to convert tabs to X spaces.

Others would say keep them as tabs.

I say, if you are seeking help from others, make the code as easy to see/follow/understand as possible...

David (aka frog_jr)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

  cbc02009 wrote:

and fixed some of the problems you mentioned.

But not all of them ;-) :

 

joeymorin wrote:

You're using CTC mode where OCR1A is TOP, but you set OCR1B.

 

 cbc02009 wrote:

Anyway, thank you all for your help. I figured it out. I had timer 1 set to count to OCR1A, but I never put a value in OCR1A. Very stupid >_<

There you go!

"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]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:

cbc02009 wrote:
 it's aligned almost perfect in atmel studio, but not in the post for some reason.

That'll be because you've used TABs.

 

This is the very reason why you should never use TABs - always use spaces.

 

You know where you are with spaces - but TABs are completely at the mercy of the (mis)configuration of each and every individual instance of each and every  different thing that gets used to view them.

 

Any decent programmers editor will have the option to insert spaces when you press the TAB button.

Pretty sure Atmel Studio can also do it.

 

Many programmers editors have a facility to "de-TAB"; ie, convert all existing TABs toappropriate numbers of spaces.

 

#TabsAreEvil #SpacesNotTabs

 

'Freaks have been here before; recently.  My response to you in https://www.avrfreaks.net/comment... includes

Bull.  Who appointed y'all editing police?

 

First, then, remove TAB from the character sets.  Now, depending on your coloration, you might make a distinction between horizontal tabs and vertical tabs.  One can ascertain which group -- "good TAB" or "bad TAB" -- needs to be suppressed by observing which end of the boiled egg is broken first.

 

After the successful purge of TAB from the control characters section of character-set standards, the actual intent of the self-appointed evil cabal will be revealed. The TAB situation is just a feint; the real purpose is to attach the alphabet itself.  First target :  "F".  After all, without it there would be no F-word.

 

Following such adjustment to "content" I suppose "style" is next.  You mind my words -- if this continues, someone will start campaigning for 1TBS and anyone that disagrees will be subject to Darci Lynne  https://www.youtube.com/watch?v=... until they do, just like during other similar Inquisitions.

 

 

 

Please label the above as your opinion/vote.  Please don't present it as fact, as you might with e.g. the parameters for an op code.

 

My opinion is the opposite.  Also IMO, OP's second code doesn't look so bad.  Yes, all the comments don't exactly line up.  I can still get the gist for this thread's purposes.  Please blame that [the lack of total alignment] on the imperfect <> code tags implementation.  [if you claim "perfect" on that I'll have further lambasting in the wings]

 

Again, just my opinion.  But I've only been at this for 45+ years.  Maybe that is the problem -- you young whippersnappers toss your [near] infinite-sized storage devices and [near] infinite-speed processors and [near] infinite-speed comm links at any situation.

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.

Last Edited: Wed. Dec 6, 2017 - 02:50 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:
But I've only been at this for 45+ years.  Maybe that is the problem

Tempting. Too tempting..

 

So here's my opinion:

 

Yes, it's the 45 years.

 

Tabs where invented on mechanical typewriters, where they where a big relief when you wanted to do tables and the like.

 

On terminals (paper ones), teletypes etc there still was a good reason to use tabs, since movement of the print assembly possibly was faster. For terminals connected over relatively slow lines to a mainframe it saved a bit on bits transferred. At 300 bps it might have been significant.

 

A case could even be made for tabs saving secondary storage space when a 320 KB diskette still was a large secondary memory.

 

I grew up with everything above.

 

But 45 years later none of those rationales are significant, and any modern editor does "smart" indentation that is configurable to your wishes. Even when it inserts spaces rather than tabs.

 

In my opinion it's a matter of accepting change with time passing (I don't do punched cards anymore). And that tabs become a mess when you don't know or can't affect how they are rendered. I still remember when we had the tab stops specified in every source file. I don't miss that.

 

The tab stops being at every eight position is also historical, and nowadays is completely useless for formatting code. How on earth could the code editor people select that as default is beyond me. Tab stops every 2, 3 or 4 positions makes more sense to me. (Actually 2 is my current favourite, but I'll adopt to the convention of the project I'm currently working in.)

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:
Please label the above as your opinion/vote.  Please don't present it as fact, as you might with e.g. the parameters for an op code.

I beg to differ.

 

It is a fact that the result of a TAB character is undefined - therefore, you cannot rely up on it.

 

If you cannot rely upon it, then you should not rely upon it.

 

Please blame that [the lack of total alignment] on the imperfect <> code tags implementation

No,  it has nothing to do with the failings of the lamentable code editor - the code editor is behaving entirely reasonably in this respect.

 

 

you young whippersnappers 

Yeah - I've only been at it for 35 years.

 

And in that time I've seen far to much text layout messed up due to reliance on TABs.

 

Just Say No!

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:
It is a fact that the result of a TAB character is undefined - therefore, you cannot rely up on it.

I beg to differ.  No more undefined than Enter key action.

 

If I continue, I'll be lambasted for being a surly curmudgeon.  Neither you nor your minions [ ;) i.e. those of your like mind on this]  have been granted any authority in this matter. [Dilly! Dilly! https://www.thrillist.com/news/n...

 

 

 

 

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.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:
I beg to differ. 

Go on, then - give us a definition of the result (or "effect") of a TAB character...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You go first -- definitive action with the press of the Enter key.

 

 

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.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No, there isn't one - but how does that have anything to do with TABs?

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Enter key can result in any of CR, LF, or CR+LF. That, to me, is relatively undefined. Not much different than nxSPACE.

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You're missing the point.

 

The point is that, if you put TABs in your text, then the layout cannot be guaranteed.

 

If you want the layout of your code to be consistent, then you must not use TABs - you must use only spaces for layout.

 

Of course, if you're happy for your layout to go to pot each time the code is viewed on a different system - as seen in #3, and countless other posts here and elsewhere - then go ahead and use TABs!

 

(the code in #3 is lucky in that pretty much the only indentation is a constant left margin - so only the comments are affected by the TAB interpretation)

 

EDIT

 

It occurs that  I have actually said the same thing about the enter key - ie, that it can't be relied upon so, if you need to be certain of getting specifically CR or LF or CRLF then you have to manually use ^J and/or ^M.

 

but will I be able to find an example ... ?

 

EDIT 2

 

Here: https://www.avrfreaks.net/comment...

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Sun. Dec 24, 2017 - 01:47 AM