Advertisement
Harry_L

8bit PWM with Shift-Register

Mar 18th, 2019
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.24 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 <stdio.h>
  11. #include "uart.h"
  12. #include "pwm8.h"
  13.  
  14. #define LED_NUM     8// must be a multiple of 8
  15.  
  16. #define DEBUG
  17.  
  18. #define LATCH_PIN   PB1     // STCP
  19. #define OE_PIN      PB2     // OE
  20. #define MOSI_PIN    PB3     // Din
  21. #define CLK_PIN     PB5     // SHCP
  22.  
  23. #define PORT_DIR    DDRB
  24. #define OUT_PORT    PORTB
  25.  
  26. #define LATCH()     OUT_PORT |= (1 << LATCH_PIN),OUT_PORT &= ~(1 << LATCH_PIN)
  27.  
  28. #ifdef DEBUG
  29. #define TRIGGER_PIN PD2     // Debug-pin for triggering
  30. #define TRIGGER_DIR DDRD
  31. #define TRIGGER_PORT    PORTD
  32. #define TRIGGER()   TRIGGER_PORT ^= (1 << TRIGGER_PIN) //,PULSE_PORT &= ~(1 << TRIGGER_PIN)
  33. #endif
  34.  
  35. #define TIM_BSY()   tim_bsy = TRUE
  36. #define TIM_RDY()   tim_bsy = FALSE
  37. #define SPI_BSY()   spi_bsy = TRUE
  38. #define SPI_RDY()   spi_bsy = FALSE
  39.  
  40. /*
  41.  * timingg-setting
  42.  */
  43. #define DEADTIME    8
  44.  
  45. static volatile uint8_t pwm_buf[LED_NUM];
  46.  
  47. static volatile uint8_t tim_bsy = FALSE;
  48. static volatile uint8_t spi_bsy = FALSE;
  49. static volatile uint16_t bit_cnt = 0;
  50. static volatile uint8_t dummy;
  51.  
  52. /*
  53.  * Public Functions
  54.  */
  55. void pwm8Init(void)
  56. {
  57.     // Initialize GPIOs
  58.     PORT_DIR |= ((1 << LATCH_PIN) | (1 << OE_PIN)
  59.              | (1 << MOSI_PIN) | (1 << CLK_PIN));   // define Outputs
  60. #ifdef DEBUG
  61.     TRIGGER_DIR |= (1 << TRIGGER_PIN);
  62. #endif
  63.  
  64.     OUT_PORT &= ~((1 << LATCH_PIN) | (1 << OE_PIN));    // Reset Latch and OE
  65.  
  66.     // Initialize SPI
  67.     SPCR = (1 << SPIE) | (1 << SPE) | (1 << MSTR);  // enable SPI
  68.     dummy = SPSR;   // clear pending interrupts
  69.     dummy = SPDR;
  70.  
  71.     // Initialize Timer
  72.  
  73.  
  74.     TCCR1A = 0;
  75.     TCCR1A = (1 << COM1B1) | (1 << WGM11);
  76.     TCCR1B = (1 << WGM12) | (1 << WGM13)
  77.             | (1 << CS11) | (1 << CS10);    // fast PWM-Mode
  78.     TCNT1 = 0;
  79.     GTCCR = ((1 << PSRSYNC) | (1 << TSM) | (1 << PSRASY));  // disable & synchronize prescaler
  80.  
  81.     TIFR1 = (1 << OCF1B);   // clear any pending interrupt
  82.     TIMSK1 = (1 << ICIE1);//  | (1 << TOIE1);   // enable OC0A interrupt
  83.     sei();
  84.  
  85.     // Start first SPI-transfer
  86.     SPDR = pwm_buf[bit_cnt];
  87.     SPI_BSY();
  88. }
  89.  
  90. /*
  91.  * Set LED Nr. lednr
  92.  * to PWM-Value pwm_val
  93.  */
  94. void pwm8SetLED(uint8_t lednr, uint8_t pwm_val)
  95. {
  96.     uint8_t pwm_mask, led_mask;
  97.     pwm_mask = 1;
  98.     led_mask = 1 << lednr;
  99.     for (uint8_t i = 0; i < 8; i++)
  100.     {
  101.         if ((pwm_val & pwm_mask) == 0)
  102.         {
  103.             pwm_buf[i] = pwm_buf[i] | led_mask;
  104.         }
  105.         else
  106.         {
  107.             pwm_buf[i] = pwm_buf[i] & ~led_mask;
  108.         }
  109.         pwm_mask <<= 1;
  110.     }
  111.  
  112. }
  113.  
  114. /*
  115.  * Private Functions
  116.  */
  117.  
  118.     // sart next Cycle
  119. static void pwm8KickCycle(void)
  120. {
  121.  
  122.     LATCH();    // enable new data
  123. #ifdef DEBUG
  124.     if (bit_cnt == 0)
  125.         TRIGGER();
  126. #endif
  127.  
  128.     // setup one-pulse-timer
  129.     ICR1 = (1 << bit_cnt) + DEADTIME;
  130.     OCR1B = DEADTIME;
  131.  
  132.     TCNT1 = 0;
  133.     GTCCR = 0;              // enable Prescaler and start Timer
  134.     TIM_BSY();              // timer running
  135.  
  136.     bit_cnt = (bit_cnt +1) & 0b00000111; // advance to next cycle
  137.     SPDR = pwm_buf[bit_cnt]; // send next pattern in advance
  138.     SPI_BSY();              // SPI running
  139. }
  140.  
  141. /*
  142.  * Interrupts
  143.  *
  144.  */
  145.  
  146.     // SPI-Interrupt
  147. ISR( SPI_STC_vect )
  148. {
  149.     dummy = SPDR;
  150.     SPI_RDY();
  151.     if (tim_bsy == FALSE)
  152.         pwm8KickCycle();
  153. }
  154.  
  155.      // Timer Interrupt
  156. ISR( TIMER1_CAPT_vect )
  157. {
  158.     GTCCR = (1<<TSM) | (1<<PSRASY) | (1<<PSRSYNC); // halt all timers
  159.     TIM_RDY();
  160.     if (spi_bsy == FALSE)
  161.         pwm8KickCycle();
  162. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement