Advertisement
Harry_L

8bit PWM w. n SRs (fehlerbereinigt)

Mar 19th, 2019
540
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.07 KB | None | 0 0
  1. /*
  2.  * pwm8.c
  3.  *
  4.  *  Created on: 10.03.2019
  5.  *      Author: harry
  6.  */
  7.  
  8. #include "avr/io.h"
  9. #include <avr/interrupt.h>
  10. #include "pwm8.h"
  11.  
  12. /*
  13.  * User adjustable
  14.  */
  15. #define LED_NUM     8               // must be a multiple of 8
  16.                                     // limited by amount of RAM
  17. #define DEBUG                       // enable scope-trigger-signal-pin
  18.  
  19. #ifdef DEBUG
  20. #define TRIGGER_PIN PD2             // Debug-pin for scope-triggering
  21. #define ACTIVE_PIN  PD3
  22. #define DEBUG_DIR   DDRD
  23. #define DEBUG_PORT  PORTD
  24. #endif
  25.  
  26. #define LATCH_PIN   PB1             // STCP
  27. #define OE_PIN      PB2             // OE
  28. #define MOSI_PIN    PB3             // Din
  29. #define CLK_PIN     PB5             // SHCP
  30.  
  31. #define PORT_DIR    DDRB
  32. #define LED_PORT    PORTB
  33.  
  34. /*
  35.  * timingg-setting
  36.  */
  37. #define DEADTIME    24              // increase value, if you have other more time
  38.                                     // consuming interrupts and the shortest pulses gets doubled
  39. /*
  40.  * don't change anything below this line!
  41.  * except, you know, what are you going to do!
  42.  */
  43. #define LATCH()     LED_PORT |= (1 << LATCH_PIN),LED_PORT &= ~(1 << LATCH_PIN)
  44.  
  45. #ifdef DEBUG
  46. #define TRIGGER()   DEBUG_PORT ^= (1 << TRIGGER_PIN) //,PULSE_PORT &= ~(1 << TRIGGER_PIN)
  47. #define LEAVE_INT()     DEBUG_PORT |= (1 << ACTIVE_PIN)
  48. #define ENTER_INT()     DEBUG_PORT &= ~(1 << ACTIVE_PIN)
  49. #endif
  50.  
  51. #define SR_NUM      (LED_NUM / 8)
  52.  
  53. #define TIM_BSY()   tim_bsy = TRUE
  54. #define TIM_RDY()   tim_bsy = FALSE
  55. #define SPI_BSY()   spi_bsy = TRUE
  56. #define SPI_RDY()   spi_bsy = FALSE
  57.  
  58. static volatile uint8_t pwm_buf[SR_NUM][8];
  59.  
  60. static volatile uint8_t tim_bsy = FALSE;
  61. static volatile uint8_t spi_bsy = FALSE;
  62. static volatile uint8_t bit_cnt = 0;
  63. static volatile uint8_t sr_cnt;
  64. static volatile uint8_t dummy;
  65.  
  66. /*
  67.  * Public Functions
  68.  */
  69. void pwm8Init(void)
  70. {
  71.     // Initialize GPIOs
  72.     PORT_DIR |= ((1 << LATCH_PIN) | (1 << OE_PIN)
  73.              | (1 << MOSI_PIN) | (1 << CLK_PIN));   // define Outputs
  74.     LED_PORT &= ~((1 << LATCH_PIN) | (1 << OE_PIN));    // Reset Latch and OE
  75.  
  76. #ifdef DEBUG
  77.     DEBUG_DIR |= ((1 << TRIGGER_PIN) | (1 << ACTIVE_PIN));
  78. #endif
  79.  
  80.     // Initialize SPI
  81.     SPCR = (1 << SPIE) | (1 << SPE) | (1 << MSTR);  // enable SPI
  82.     dummy = SPSR;   // clear pending interrupts
  83.     dummy = SPDR;
  84.  
  85.     // Initialize Timer
  86.     TCCR1A = (1 << COM1B1) | (1 << WGM11);
  87.     TCCR1B = (1 << WGM12) | (1 << WGM13)
  88.             | (1 << CS11);      // fast PWM-Mode
  89.     TCNT1 = 0;
  90.     GTCCR = ((1 << PSRSYNC) | (1 << TSM) | (1 << PSRASY));  // disable & synchronize prescaler
  91.  
  92.     TIFR1 = (1 << OCF1B);   // clear any pending interrupt
  93.     TIMSK1 = (1 << ICIE1);  // enable OC0A interrupt
  94.     sei();
  95.  
  96.     // Start first SPI-transfer
  97.     sr_cnt = 0;
  98.     SPDR = pwm_buf[sr_cnt][bit_cnt];
  99.     SPI_BSY();
  100. }
  101.  
  102. /*
  103.  * Set LED Nr. lednr
  104.  * to PWM-Value pwm_val
  105.  */
  106. void pwm8SetLED(uint16_t lednr, uint8_t pwm_val)
  107. {
  108. uint8_t pwm_mask, led_mask;
  109. uint8_t sr;
  110.  
  111.     sr = lednr >> 3;
  112.     pwm_mask = 1;
  113.     led_mask = 1 << (lednr & 0b00000111);
  114.     for (uint8_t i = 0; i < 8; i++)
  115.     {
  116.         if ((pwm_val & pwm_mask) == 0)
  117.         {
  118.             pwm_buf[sr][i] = pwm_buf[sr][i] | led_mask;
  119.         }
  120.         else
  121.         {
  122.             pwm_buf[sr][i] = pwm_buf[sr][i] & ~led_mask;
  123.         }
  124.         pwm_mask <<= 1;
  125.     }
  126. }
  127.  
  128. /*
  129.  * Private Functions
  130.  */
  131.     // stat next Cycle
  132. static void pwm8KickCycle(void)
  133. {
  134.  
  135.     LATCH();    // enable new data
  136. #ifdef DEBUG
  137.     if (bit_cnt == 0)
  138.         TRIGGER();
  139. #endif
  140.  
  141.     // setup one-pulse-timer
  142.     ICR1 = (1 << bit_cnt) + DEADTIME;
  143.     OCR1B = DEADTIME;
  144.  
  145.     TCNT1 = 0;
  146.     GTCCR = 0;              // enable Prescaler and start Timer
  147.     TIM_BSY();              // timer running
  148.  
  149.     bit_cnt = (bit_cnt +1) & 0b00000111; // advance to next cycle
  150.     SPDR = pwm_buf[0][bit_cnt]; // send next pattern in advance
  151.     SPI_BSY();              // SPI running
  152.     LEAVE_INT();
  153. }
  154.  
  155. /*
  156.  * Interrupts
  157.  *
  158.  */
  159.     // SPI-Interrupt
  160. ISR( SPI_STC_vect )
  161. {
  162.     ENTER_INT();
  163.     dummy = SPDR;
  164.     if (++sr_cnt == SR_NUM)
  165.     {
  166.         SPI_RDY();
  167.         sr_cnt = 0;
  168.         if (tim_bsy == FALSE)
  169.             pwm8KickCycle();        // this is a special case, where the
  170.                                     // SPI-transfer takes longer than the timer-cycle
  171.     }
  172.     else
  173.     {
  174.         SPDR = pwm_buf[sr_cnt][bit_cnt];
  175.     }
  176.     LEAVE_INT();
  177. }
  178.  
  179.      // Timer Interrupt
  180. ISR( TIMER1_CAPT_vect )
  181. {
  182.     ENTER_INT();
  183.     GTCCR = (1<<TSM) | (1<<PSRASY) | (1<<PSRSYNC); // halt all timers
  184.     TIM_RDY();
  185.     if (spi_bsy == FALSE)
  186.         pwm8KickCycle();
  187.     LEAVE_INT();
  188. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement