Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #ifndef F_CPU
- #define F_CPU 16000000UL
- #endif
- /***
- MD Harrington Kent London 04/02/2024 Time now 05:13
- And at 05:13 for some way over 5 hours and more since 10pm yesterday I am busying learning on self taught basis
- Follow this link for visual display of what this does
- https://www.instagram.com/p/C4FHGeYgG84/
- https://www.facebook.com/100007080936840/videos/pcb.3658450727734256/709978437955735
- ***/
- #include <avr/interrupt.h>
- #include <avr/io.h>
- #include <util/delay.h>
- /* registers used
- PCICR -> port control interrupt change register so to enable this we set the lower 3 bits to which port we are
- {
- PCIE0 is for port B
- PCIE1 is for port C // Im using port c for switching
- PCIE2 is for port D
- }
- We use a mask to select which pin we ofthe port we want to interrupt on
- PCMSK0 is mask for Port B
- PCMSK1 is mask for Port C
- PCMSK2 is mask for Port D
- PCIFR -> Port control Interrupt flag register
- {
- PCIF2 -> Interrupt flag for Port D
- PCIF1 -> Interrupt flag for Port C
- PCIF0 -> Interrupt flag for Port B
- }
- The DDX Register -> This is for setting up port direction
- DDRB -> PortB
- DDRC -> PortC
- DDRD -> PortD
- */
- volatile uint8_t portdhistory = 0x00;
- volatile uint8_t debounceFlag = 0; // Flag to control debounce
- /* Notes On volatile
- In the context of microcontroller programming, using volatile is common when dealing with memory-mapped hardware registers
- or variables that are accessed within interrupt service routines (ISRs). Here's the effect of declaring variables as volatile:
- Prevents Optimization: Without the volatile keyword, the compiler may optimize code by caching the value of a variable in a register or by reordering instructions.
- This optimization could cause issues if the variable's value can be changed by external factors, such as hardware peripherals or ISRs.
- Declaring the variable as volatile ensures that the compiler always reads the variable's value from memory
- and does not apply optimizations that assume the value remains unchanged.
- Memory Access: When a variable is declared as volatile, the compiler will generate code to read or write the variable directly
- from memory every time it is accessed, ensuring that the most up-to-date value is used.
- Interactions with Interrupts and Hardware: In embedded systems programming, hardware peripherals
- (such as timers, GPIO ports, etc.) may modify variables that are accessed in both normal code and interrupt service routines.
- Declaring these variables as volatile ensures that the compiler does not optimize away accesses to these variables,
- allowing correct behavior in the presence of interrupts and hardware interactions.
- In your example, portdhistory and debounceFlag are likely accessed and modified by both the main code and an interrupt service routine (ISR).
- Therefore, declaring them as volatile ensures that the compiler does not optimize away their accesses and correctly handles their interaction with interrupts.
- */
- // Protoype functions
- void init() ;
- void init(){
- // Enable Pin Change Interrupt on PORTC
- PCICR |= (1 << PCIE1); // Enables PCMSK1 scan
- // Enable the Pin Change Interrupt for PC0 (pin 14)
- PCMSK1 |= (1 << PCINT8);
- // Set up port direction for PORTD as output
- DDRD = 0xFF;
- // Set up PORTC0 (pin 14) as input with internal pull-up enabled
- DDRC &= ~(1 << DDC0);
- PORTC |= (1 << PORTC0);
- portdhistory =0x80 ;
- // Configure Timer1 for debounce delay
- TCCR1B |= (1 << WGM12); // CTC mode
- /*
- CTC stands for "Clear Timer on Compare Match".
- It's a mode available in many AVR microcontrollers like those found in Arduino boards.
- In CTC mode, the timer counts up until it reaches a specified value (the "compare match" value) stored in the compare match register (OCRn).
- When the count matches this value, the timer is cleared (reset to zero), and an interrupt can be generated.
- CTC mode is useful for generating precise time intervals or for creating periodic events.
- By adjusting the compare match value, you can control the duration between interrupts, allowing for precise timing control.
- */
- OCR1A = 625; // For 10ms debounce delay with 16MHz CPU frequency
- /*
- Determine Clock Frequency (f_clk):
- You've specified the clock frequency as 16 MHz (F_CPU).
- Choose Prescaler Value (N):
- Let's choose a prescaler value of 64. This value divides the clock frequency to determine the timer's count rate.
- Calculate Timer Tick Duration (T_tick):
- Use the formula: Ttick=1fclk/NTtick=fclk/N1
- For our case: Ttick=116×106/64=6416×106=4×10−6Ttick=16×106/641=16×10664=4×10−6 seconds.
- Determine Number of Timer Ticks for 10 ms Delay:
- Since we want a 10 ms delay, we need to determine how many timer ticks represent 10 ms.
- Use the formula: Number of ticks=Delay (in seconds)TtickNumber of ticks=TtickDelay (in seconds)
- For a 10 ms delay: Number of ticks=10×10−34×10−6=2500
- Number of ticks=4×10−610×10−3=2500
- Check Range:
- Ensure the calculated number of ticks fits within the range of a 16-bit timer (0 to 65535).
- Load Value into OCR1A Register:
- Finally, load the calculated value (2500) into the OCR1A register to achieve a 10 ms delay.
- */
- TIMSK1 |= (1 << OCIE1A); // Enable compare match interrupt
- }
- // define the ISR
- ISR (PCINT1_vect)
- {
- if (!debounceFlag) {
- debounceFlag = 1; // Set debounce flag
- TCNT1 = 0; // Reset timer count
- TCCR1B |= (1 << CS11) | (1 << CS10); // Start Timer1 with prescaler 64
- }
- }
- ISR(TIMER1_COMPA_vect) {
- uint8_t changedBits = PINC; // Read the current status of PORTC
- if (changedBits & (1 << PINC0)) { // Check if the change occurred on pin PC0
- portdhistory >>= 1; // Shift the port value to the right by one
- }
- TCCR1B = 0; // Stop Timer1
- debounceFlag = 0; // Clear debounce flag
- }
- int main() {
- init();
- sei();
- while (1) {
- PORTD = portdhistory; // Write the updated port value to PORTD
- // If portdhistory reaches 0x02, reset it to 0x08
- if (portdhistory == 0x02) {
- portdhistory = 0x80;
- }
- }
- } //end main
- /* Additional notes of this who dont really like the idea of compiling etc all of which is part and parcel of this then here is the compiled code in hex ready to upload to your MCU below and this is where you can do all sorts just within that hex Think about that in depth and you will soon realise something else you perhaps never eben thought about
- :020000040000FA
- :100000000C9434000C9446000C9446000C9446006A
- :100010000C9463000C9446000C9446000C9446002B
- :100020000C9446000C9446000C9446000C94480036
- :100030000C9446000C9446000C9446000C94460028
- :100040000C9446000C9446000C9446000C94460018
- :100050000C9446000C9446000C9446000C94460008
- :100060000C9446000C94460011241FBECFEFD8E03C
- :10007000DEBFCDBF21E0A0E0B1E001C01D92A23003
- :10008000B207E1F70E947F000C94AC000C940000D2
- :100090001F920F920FB60F9211248F939F93309B54
- :1000A00007C08091010190E09595879580930101AB
- :1000B00010928100109200019F918F910F900FBEBE
- :1000C0000F901F9018951F920F920FB60F92112448
- :1000D0008F938091000181110CC081E08093000119
- :1000E000109285001092840080918100836080933B
- :1000F00081008F910F900FBE0F901F9018958091E7
- :10010000680082608093680080916C0081608093B9
- :100110006C008FEF8AB93898409A80E8809301018B
- :100120008091810088608093810081E792E09093C4
- :1001300089008093880080916F00826080936F00B7
- :10014000789480E8909101019BB9909101019230DF
- :0C015000C9F780930101F6CFF894FFCFAF
- :107E0000112484B714BE81FFF0D085E080938100F7
- :107E100082E08093C00088E18093C10086E0809377
- :107E2000C20080E18093C4008EE0C9D0259A86E02C
- :107E300020E33CEF91E0309385002093840096BBD3
- :107E4000B09BFECF1D9AA8958150A9F7CC24DD24C4
- :107E500088248394B5E0AB2EA1E19A2EF3E0BF2EE7
- :107E6000A2D0813461F49FD0082FAFD0023811F036
- :107E7000013811F484E001C083E08DD089C08234E0
- :107E800011F484E103C0853419F485E0A6D080C0E4
- :107E9000853579F488D0E82EFF2485D0082F10E0AE
- :107EA000102F00270E291F29000F111F8ED06801E7
- :107EB0006FC0863521F484E090D080E0DECF843638
- :107EC00009F040C070D06FD0082F6DD080E0C81688
- :107ED00080E7D80618F4F601B7BEE895C0E0D1E017
- :107EE00062D089930C17E1F7F0E0CF16F0E7DF06D8
- :107EF00018F0F601B7BEE89568D007B600FCFDCFD4
- :107F0000A601A0E0B1E02C9130E011968C91119780
- :107F100090E0982F8827822B932B1296FA010C0160
- :107F200087BEE89511244E5F5F4FF1E0A038BF0790
- :107F300051F7F601A7BEE89507B600FCFDCF97BE46
- :107F4000E89526C08437B1F42ED02DD0F82E2BD052
- :107F50003CD0F601EF2C8F010F5F1F4F84911BD097
- :107F6000EA94F801C1F70894C11CD11CFA94CF0C13
- :107F7000D11C0EC0853739F428D08EE10CD085E9AC
- :107F80000AD08FE07ACF813511F488E018D01DD067
- :107F900080E101D065CF982F8091C00085FFFCCF94
- :107FA0009093C60008958091C00087FFFCCF809118
- :107FB000C00084FD01C0A8958091C6000895E0E648
- :107FC000F0E098E1908380830895EDDF803219F02E
- :107FD00088E0F5DFFFCF84E1DECF1F93182FE3DFCA
- :107FE0001150E9F7F2DF1F91089580E0E8DFEE27F6
- :047FF000FF270994CA
- :027FFE00040479
- :00000001FF
- */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement