Advertisement
igendel

Picadom board demo #1

Sep 2nd, 2018
200
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.91 KB | None | 0 0
  1. /*
  2.  * Picadom board demo program
  3.  * by Ido Gendel, 2018
  4.  *
  5.  * Hardware on board:
  6.  * - LED anode connected to RA0
  7.  * - Momentary switch (N.O.) between GND and RA2
  8.  *
  9.  * Software:
  10.  * - MPLAB X IDE v5.00
  11.  * - XC8 compiler v2.00 (Free edition)
  12.  *
  13.  * Reference:
  14.  * - PIC12(L)F1840 Datasheet, revision DS40001441F
  15.  */
  16.  
  17. // PIC12F1840 Configuration Bit Settings
  18. // These settings are defined outside the normal code.
  19. // See menu Window->Target Memory Views->Configuration Bits
  20. #pragma config FOSC = INTOSC    // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)
  21. #pragma config WDTE = SWDTEN    // Watchdog Timer Enable (WDT controlled by the SWDTEN bit in the WDTCON register)
  22. #pragma config PWRTE = ON       // Power-up Timer Enable (PWRT enabled)
  23. #pragma config MCLRE = ON       // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
  24. #pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
  25. #pragma config CPD = OFF        // Data Memory Code Protection (Data memory code protection is disabled)
  26. #pragma config BOREN = ON       // Brown-out Reset Enable (Brown-out Reset enabled)
  27. #pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
  28. #pragma config IESO = OFF       // Internal/External Switchover (Internal/External Switchover mode is disabled)
  29. #pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is disabled)
  30. #pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
  31. #pragma config PLLEN = OFF      // PLL Enable (4x PLL disabled)
  32. #pragma config STVREN = ON      // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
  33. #pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
  34. #pragma config LVP = ON         // Low-Voltage Programming Enable (Low-voltage programming enabled)
  35.  
  36. // This is used for the built-in delay functions
  37. // Make sure it agrees with any clock settings in the code
  38. #define _XTAL_FREQ 8000000UL
  39.  
  40. #define BLINK_PADDING_MS 1000
  41. #define BLINK_HIGH_MS 100
  42. #define BLINK_LOW_MS 200
  43.  
  44. #include <xc.h>
  45. #include <stdint.h>
  46.  
  47. // This demo will be run as a "state machine"
  48. #define DEMO_MODES 2
  49. struct tDemoMode {
  50.         // Function pointers are fun!
  51.         void (*runCallback)(void);
  52.     } demoMode[DEMO_MODES];
  53.  
  54. // This variable will be changed in an interrupt service routine
  55. // So we declare it volatile to avoid problematic compiler optimizations    
  56. volatile uint8_t switchPressed = 0;
  57.    
  58. //=========================================================
  59. // Power-saving blink, Watchdog-based
  60. // Make sure the configuration bit WDTE is SWDTEN (see above)
  61. void runM0(void) {
  62.    
  63.     const uint8_t stateWDTPS[2] = {0x0A, 0x04};
  64.     uint8_t state = 1;
  65.    
  66.     // Enable watchdog
  67.     WDTCONbits.SWDTEN = 1;
  68.    
  69.     while (!switchPressed) {
  70.  
  71.         // Set watchdog prescaler (1s or 16ms - see Datasheet p. 83)
  72.         WDTCONbits.WDTPS = stateWDTPS[state];
  73.         // LED OFF or ON
  74.         LATAbits.LATA0 = state;  
  75.         // Save CPU power!
  76.         SLEEP();
  77.         // Woke up either by watchdog or interrupt...
  78.         state = 1 - state;
  79.        
  80.     }
  81.    
  82.     // Disable watchdog
  83.     WDTCONbits.SWDTEN = 0;
  84.    
  85. } // runM0
  86.  
  87. //=========================================================
  88. // Run a single cycle of the software-based PWM signal
  89. void swPWM(uint8_t v) {
  90.    
  91.     uint16_t n;
  92.    
  93.     // A dumb loop, but the timing turns out easy on the eyes
  94.     for (n = 0; n < 256; ++n) {
  95.         LATAbits.LATA0 = (n < v) ? 1 : 0;
  96.     }
  97.    
  98. } // swPWM
  99.  
  100. //=========================================================
  101. // LED breath effect, lazy software-based PWM
  102. void runM1(void) {
  103.    
  104.     uint8_t v = 0;
  105.     int8_t dir = -1;
  106.    
  107.     while (!switchPressed) {
  108.        
  109.         swPWM(v);
  110.         if ((0 == v) || (255 == v)) {
  111.             dir = -dir;
  112.         }
  113.         v += dir;
  114.        
  115.     }
  116.  
  117. } // runM1
  118.  
  119. //=========================================================
  120. void setup(void) {
  121.    
  122.     // Internal oscillator set to 500KHz on reset. We'll set it to 8MHz, no PLL
  123.     // (note that on PIC MCUs, each instruction cycle is 4 clock cycles)
  124.     // Datasheet p. 53
  125.     // The "[register name]bits" structs give us direct access to register sub-byte units
  126.     OSCCONbits.IRCF = 0x0EU;
  127.  
  128.     // Assign callback functions for the state machine
  129.    
  130.     demoMode[0].runCallback = runM0;
  131.     demoMode[1].runCallback = runM1;
  132.  
  133.     // Set up RA0 as regular digital output and LOW
  134.    
  135.     // In PIC MCUs, a tri-state value of 0 means output, 1 means input
  136.     TRISAbits.TRISA0 = 0;
  137.     // Disable analog input
  138.     ANSELAbits.ANSA0 = 0;
  139.     // Latch the output to LOW
  140.     LATAbits.LATA0 = 0;    
  141.    
  142.     // Set up RA2 for external interrupt; Datasheet p. 71
  143.    
  144.     // In PIC MCUs, a tri-state value of 0 means output, 1 means input    
  145.     TRISAbits.TRISA2 = 1;
  146.     // Disable analog input
  147.     ANSELAbits.ANSA2 = 0;
  148.     // Enable weak pull-up, but disable on all other pins
  149.     WPUA = 0;
  150.     WPUAbits.WPUA2 = 1;
  151.     // Global weak pull-up enable, negative logic
  152.     OPTION_REGbits.nWPUEN = 0;
  153.     // Interrupt on falling edge
  154.     OPTION_REGbits.INTEDG = 0;
  155.     // Enable external interrupt, then interrupts globally
  156.     INTCONbits.INTE = 1;
  157.     INTCONbits.GIE = 1;
  158.    
  159. } // setup
  160.  
  161. //=========================================================
  162. void blink(uint8_t times) {
  163.  
  164.    // Blink with pre- and post-padding intervals
  165.    
  166.     __delay_ms(BLINK_PADDING_MS);
  167.    
  168.     while (times--) {
  169.        
  170.         LATAbits.LATA0 = 1;
  171.         __delay_ms(BLINK_HIGH_MS);
  172.  
  173.         LATAbits.LATA0 = 0;
  174.         __delay_ms(BLINK_LOW_MS);
  175.        
  176.     } // while
  177.    
  178.     __delay_ms(BLINK_PADDING_MS);
  179.    
  180. } // blink
  181.  
  182.  
  183. //=========================================================
  184. void main(void) {
  185.    
  186.     uint8_t currentMode = 0;
  187.    
  188.     setup();
  189.    
  190.     while (1) {
  191.  
  192.         // Blink current mode. +1, because we can't blink 0 times
  193.         blink(currentMode + 1);
  194.         // That also served as a debounce period, so don't press too long :-)
  195.      
  196.         // The switch press serves as a generic "stop" command
  197.         switchPressed = 0;
  198.         demoMode[currentMode].runCallback();
  199.        
  200.         ++currentMode;
  201.         if (DEMO_MODES == currentMode) {
  202.             currentMode = 0;
  203.         }
  204.  
  205.     } // while
  206.    
  207.     return;
  208.    
  209. } // main
  210.  
  211. //=========================================================
  212.  
  213. // Most PICs only have a single interrupt vector.
  214. // The interrupt source has to be determined inside this function
  215. void __interrupt() ISR(void) {
  216.    
  217.     // We defined only one interrupt source (external), so no checks necessary
  218.     switchPressed = 1;
  219.     // Clear the interrupt flag
  220.     INTCONbits.INTF = 0;
  221.    
  222. } // ISR
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement