Advertisement
Mark2020H

avr -gcc code using port pin change and timer capture and compare

Mar 3rd, 2024 (edited)
1,245
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.27 KB | Software | 0 0
  1. #ifndef F_CPU
  2. #define F_CPU 16000000UL
  3. #endif
  4.  
  5. /***
  6.  
  7. MD Harrington  Kent  London 04/02/2024 Time  now 05:13
  8.  
  9. And at 05:13 for some  way over 5 hours and more  since 10pm yesterday I  am busying learning on self taught basis
  10.  
  11.  
  12. Follow this link for visual  display of what this does
  13. https://www.instagram.com/p/C4FHGeYgG84/
  14.  
  15. https://www.facebook.com/100007080936840/videos/pcb.3658450727734256/709978437955735
  16.  
  17.  
  18.  ***/
  19.  
  20.  
  21. #include <avr/interrupt.h>
  22. #include <avr/io.h>
  23. #include <util/delay.h>
  24.  
  25.  
  26. /* registers used
  27.   PCICR -> port control interrupt change register  so to enable this we set the lower 3 bits to which port we are
  28.    {
  29.         PCIE0 is for port B
  30.         PCIE1 is for port C  // Im using port c for switching
  31.         PCIE2 is for port D
  32.  
  33.   }
  34.  
  35.  
  36.   We use a  mask to select which pin  we ofthe port we want to interrupt on
  37.  
  38.  
  39.   PCMSK0 is mask for  Port B
  40.  
  41.   PCMSK1 is mask for  Port C
  42.   PCMSK2 is mask for  Port D
  43.  
  44.   PCIFR ->  Port control Interrupt flag register
  45.   {
  46.       PCIF2 -> Interrupt flag for Port D
  47.       PCIF1 -> Interrupt flag for Port C
  48.       PCIF0 -> Interrupt flag for Port B
  49.  
  50.   }
  51.  
  52.   The DDX Register -> This  is for setting up port direction
  53.  
  54.   DDRB -> PortB
  55.   DDRC -> PortC
  56.   DDRD -> PortD
  57.  
  58.  
  59. */
  60.  
  61.  
  62.  
  63. volatile uint8_t portdhistory = 0x00;
  64. volatile uint8_t debounceFlag = 0; // Flag to control debounce
  65.  
  66.  
  67. /* Notes On volatile
  68.  
  69. In the context of microcontroller programming, using volatile is common when dealing with memory-mapped hardware registers
  70. or variables that are accessed within interrupt service routines (ISRs). Here's the effect of declaring variables as volatile:
  71.  
  72. 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.
  73. This optimization could cause issues if the variable's value can be changed by external factors, such as hardware peripherals or ISRs.
  74.  
  75. Declaring the variable as volatile ensures that the compiler always reads the variable's value from memory
  76. and does not apply optimizations that assume the value remains unchanged.
  77.  
  78.     Memory Access: When a variable is declared as volatile, the compiler will generate code to read or write the variable directly
  79.     from memory every time it is accessed, ensuring that the most up-to-date value is used.
  80.  
  81.     Interactions with Interrupts and Hardware: In embedded systems programming, hardware peripherals
  82.     (such as timers, GPIO ports, etc.) may modify variables that are accessed in both normal code and interrupt service routines.
  83.    
  84.     Declaring these variables as volatile ensures that the compiler does not optimize away accesses to these variables,
  85.     allowing correct behavior in the presence of interrupts and hardware interactions.
  86.  
  87. In your example, portdhistory and debounceFlag are likely accessed and modified by both the main code and an interrupt service routine (ISR).
  88. Therefore, declaring them as volatile ensures that the compiler does not optimize away their accesses and correctly handles their interaction with interrupts.
  89.  
  90.  
  91. */
  92.  
  93.  
  94. // Protoype functions
  95.  
  96. void init() ;
  97.  
  98. void init(){
  99.  
  100.  // Enable Pin Change Interrupt on PORTC
  101.     PCICR |= (1 << PCIE1); // Enables PCMSK1 scan
  102.  
  103.     // Enable the Pin Change Interrupt for PC0 (pin 14)
  104.     PCMSK1 |= (1 << PCINT8);
  105.  
  106.     // Set up port direction for PORTD as output
  107.     DDRD = 0xFF;
  108.  
  109.     // Set up PORTC0 (pin 14) as input with internal pull-up enabled
  110.     DDRC &= ~(1 << DDC0);
  111.     PORTC |= (1 << PORTC0);
  112.  
  113.     portdhistory =0x80 ;
  114.  
  115.      // Configure Timer1 for debounce delay
  116.     TCCR1B |= (1 << WGM12); // CTC mode
  117.  
  118.     /*
  119.       CTC stands for "Clear Timer on Compare Match".
  120.       It's a mode available in many AVR microcontrollers like those found in Arduino boards.
  121.       In CTC mode, the timer counts up until it reaches a specified value (the "compare match" value) stored in the compare match register (OCRn).
  122.       When the count matches this value, the timer is cleared (reset to zero), and an interrupt can be generated.
  123.       CTC mode is useful for generating precise time intervals or for creating periodic events.
  124.       By adjusting the compare match value, you can control the duration between interrupts, allowing for precise timing control.
  125.  
  126.  
  127.     */
  128.  
  129.  
  130.     OCR1A = 625; // For 10ms debounce delay with 16MHz CPU frequency
  131.  
  132.     /*
  133.  
  134.         Determine Clock Frequency (f_clk):
  135.         You've specified the clock frequency as 16 MHz (F_CPU).
  136.  
  137.         Choose Prescaler Value (N):
  138.         Let's choose a prescaler value of 64. This value divides the clock frequency to determine the timer's count rate.
  139.  
  140.         Calculate Timer Tick Duration (T_tick):
  141.         Use the formula: Ttick=1fclk/NTtick​=fclk​/N1​
  142.         For our case: Ttick=116×106/64=6416×106=4×10−6Ttick​=16×106/641​=16×10664​=4×10−6 seconds.
  143.  
  144.         Determine Number of Timer Ticks for 10 ms Delay:
  145.         Since we want a 10 ms delay, we need to determine how many timer ticks represent 10 ms.
  146.         Use the formula: Number of ticks=Delay (in seconds)TtickNumber of ticks=Ttick​Delay (in seconds)​
  147.         For a 10 ms delay: Number of ticks=10×10−34×10−6=2500
  148.         Number of ticks=4×10−610×10−3​=2500
  149.  
  150.     Check Range:
  151.         Ensure the calculated number of ticks fits within the range of a 16-bit timer (0 to 65535).
  152.  
  153.     Load Value into OCR1A Register:
  154.         Finally, load the calculated value (2500) into the OCR1A register to achieve a 10 ms delay.
  155.  
  156.  
  157.     */
  158.  
  159.  
  160.  
  161.  
  162.     TIMSK1 |= (1 << OCIE1A); // Enable compare match interrupt
  163. }
  164.  
  165.  
  166. // define the ISR
  167.  
  168. ISR (PCINT1_vect)
  169. {
  170.  if (!debounceFlag) {
  171.         debounceFlag = 1; // Set debounce flag
  172.         TCNT1 = 0; // Reset timer count
  173.         TCCR1B |= (1 << CS11) | (1 << CS10); // Start Timer1 with prescaler 64
  174.     }
  175. }
  176.  
  177.  
  178. ISR(TIMER1_COMPA_vect) {
  179.     uint8_t changedBits = PINC; // Read the current status of PORTC
  180.     if (changedBits & (1 << PINC0)) { // Check if the change occurred on pin PC0
  181.         portdhistory >>= 1; // Shift the port value to the right by one
  182.     }
  183.  
  184.     TCCR1B = 0; // Stop Timer1
  185.     debounceFlag = 0; // Clear debounce flag
  186. }
  187.  
  188. int main() {
  189.  
  190.  
  191. init();
  192. sei();
  193.    
  194.     while (1) {
  195.            
  196.            
  197.             PORTD = portdhistory; // Write the updated port value to PORTD
  198.            
  199.              // If portdhistory reaches 0x02, reset it to 0x08
  200.         if (portdhistory == 0x02) {
  201.             portdhistory = 0x80;
  202.         }
  203.     }
  204.  
  205. } //end main
  206.  
  207. /* 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
  208.  
  209. :020000040000FA
  210. :100000000C9434000C9446000C9446000C9446006A
  211. :100010000C9463000C9446000C9446000C9446002B
  212. :100020000C9446000C9446000C9446000C94480036
  213. :100030000C9446000C9446000C9446000C94460028
  214. :100040000C9446000C9446000C9446000C94460018
  215. :100050000C9446000C9446000C9446000C94460008
  216. :100060000C9446000C94460011241FBECFEFD8E03C
  217. :10007000DEBFCDBF21E0A0E0B1E001C01D92A23003
  218. :10008000B207E1F70E947F000C94AC000C940000D2
  219. :100090001F920F920FB60F9211248F939F93309B54
  220. :1000A00007C08091010190E09595879580930101AB
  221. :1000B00010928100109200019F918F910F900FBEBE
  222. :1000C0000F901F9018951F920F920FB60F92112448
  223. :1000D0008F938091000181110CC081E08093000119
  224. :1000E000109285001092840080918100836080933B
  225. :1000F00081008F910F900FBE0F901F9018958091E7
  226. :10010000680082608093680080916C0081608093B9
  227. :100110006C008FEF8AB93898409A80E8809301018B
  228. :100120008091810088608093810081E792E09093C4
  229. :1001300089008093880080916F00826080936F00B7
  230. :10014000789480E8909101019BB9909101019230DF
  231. :0C015000C9F780930101F6CFF894FFCFAF
  232. :107E0000112484B714BE81FFF0D085E080938100F7
  233. :107E100082E08093C00088E18093C10086E0809377
  234. :107E2000C20080E18093C4008EE0C9D0259A86E02C
  235. :107E300020E33CEF91E0309385002093840096BBD3
  236. :107E4000B09BFECF1D9AA8958150A9F7CC24DD24C4
  237. :107E500088248394B5E0AB2EA1E19A2EF3E0BF2EE7
  238. :107E6000A2D0813461F49FD0082FAFD0023811F036
  239. :107E7000013811F484E001C083E08DD089C08234E0
  240. :107E800011F484E103C0853419F485E0A6D080C0E4
  241. :107E9000853579F488D0E82EFF2485D0082F10E0AE
  242. :107EA000102F00270E291F29000F111F8ED06801E7
  243. :107EB0006FC0863521F484E090D080E0DECF843638
  244. :107EC00009F040C070D06FD0082F6DD080E0C81688
  245. :107ED00080E7D80618F4F601B7BEE895C0E0D1E017
  246. :107EE00062D089930C17E1F7F0E0CF16F0E7DF06D8
  247. :107EF00018F0F601B7BEE89568D007B600FCFDCFD4
  248. :107F0000A601A0E0B1E02C9130E011968C91119780
  249. :107F100090E0982F8827822B932B1296FA010C0160
  250. :107F200087BEE89511244E5F5F4FF1E0A038BF0790
  251. :107F300051F7F601A7BEE89507B600FCFDCF97BE46
  252. :107F4000E89526C08437B1F42ED02DD0F82E2BD052
  253. :107F50003CD0F601EF2C8F010F5F1F4F84911BD097
  254. :107F6000EA94F801C1F70894C11CD11CFA94CF0C13
  255. :107F7000D11C0EC0853739F428D08EE10CD085E9AC
  256. :107F80000AD08FE07ACF813511F488E018D01DD067
  257. :107F900080E101D065CF982F8091C00085FFFCCF94
  258. :107FA0009093C60008958091C00087FFFCCF809118
  259. :107FB000C00084FD01C0A8958091C6000895E0E648
  260. :107FC000F0E098E1908380830895EDDF803219F02E
  261. :107FD00088E0F5DFFFCF84E1DECF1F93182FE3DFCA
  262. :107FE0001150E9F7F2DF1F91089580E0E8DFEE27F6
  263. :047FF000FF270994CA
  264. :027FFE00040479
  265. :00000001FF
  266.  
  267.  
  268. */
  269.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement