Skeleton program for Federico's 4YP project.
Dependencies: WebSocketClient WiflyInterface mbed messages
Fork of IoT_Ex by
source/pwm.cpp@10:e8b66718a103, 2016-11-29 (annotated)
- Committer:
- defrost
- Date:
- Tue Nov 29 15:02:01 2016 +0000
- Revision:
- 10:e8b66718a103
- Works
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
defrost | 10:e8b66718a103 | 1 | // ************** |
defrost | 10:e8b66718a103 | 2 | // * iQ_PWM.cpp * |
defrost | 10:e8b66718a103 | 3 | // ************** |
defrost | 10:e8b66718a103 | 4 | // |
defrost | 10:e8b66718a103 | 5 | // Created: 2015/03/19 |
defrost | 10:e8b66718a103 | 6 | // By: Damien Frost |
defrost | 10:e8b66718a103 | 7 | |
defrost | 10:e8b66718a103 | 8 | #include "math.h" |
defrost | 10:e8b66718a103 | 9 | #include "mbed.h" |
defrost | 10:e8b66718a103 | 10 | #include "globals.h" |
defrost | 10:e8b66718a103 | 11 | #include "pwm.h" |
defrost | 10:e8b66718a103 | 12 | #include "ADC.h" |
defrost | 10:e8b66718a103 | 13 | #include "Commands.h" |
defrost | 10:e8b66718a103 | 14 | |
defrost | 10:e8b66718a103 | 15 | #define DEBUG |
defrost | 10:e8b66718a103 | 16 | #define INFOMESSAGES |
defrost | 10:e8b66718a103 | 17 | #define WARNMESSAGES |
defrost | 10:e8b66718a103 | 18 | #define ERRMESSAGES |
defrost | 10:e8b66718a103 | 19 | #define FUNCNAME "PWM" |
defrost | 10:e8b66718a103 | 20 | #include "messages.h" |
defrost | 10:e8b66718a103 | 21 | |
defrost | 10:e8b66718a103 | 22 | |
defrost | 10:e8b66718a103 | 23 | // Configures the PWM for use, using an initial duty cycle and period in us. |
defrost | 10:e8b66718a103 | 24 | void ConfigurePWM(float duty_us, float period_us){ |
defrost | 10:e8b66718a103 | 25 | unsigned int value; |
defrost | 10:e8b66718a103 | 26 | float newVal; |
defrost | 10:e8b66718a103 | 27 | |
defrost | 10:e8b66718a103 | 28 | // Ensure power is turned on |
defrost | 10:e8b66718a103 | 29 | // Grabbed from lines 54-57 of analogin_api.h, modified for PWM |
defrost | 10:e8b66718a103 | 30 | // This turns on the clock to Ports A, B, and C |
defrost | 10:e8b66718a103 | 31 | RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOCEN; |
defrost | 10:e8b66718a103 | 32 | // This turns on the clock to the Time 1: |
defrost | 10:e8b66718a103 | 33 | RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; |
defrost | 10:e8b66718a103 | 34 | |
defrost | 10:e8b66718a103 | 35 | // Set the GPIO Ports properly: |
defrost | 10:e8b66718a103 | 36 | // PWM1 is connected to PA_8 |
defrost | 10:e8b66718a103 | 37 | // PWM1N is connected to PA_7 |
defrost | 10:e8b66718a103 | 38 | |
defrost | 10:e8b66718a103 | 39 | // Set the PWM outputs to general output pins: |
defrost | 10:e8b66718a103 | 40 | // This sets the PA_7 and PA_8 pins to Alternate Function Pins |
defrost | 10:e8b66718a103 | 41 | value = 0x8000 + 0x20000; |
defrost | 10:e8b66718a103 | 42 | GPIOA->MODER |= value; |
defrost | 10:e8b66718a103 | 43 | |
defrost | 10:e8b66718a103 | 44 | // Set the PWM outputs to high speed: |
defrost | 10:e8b66718a103 | 45 | value = 0xC000 + 0x30000; |
defrost | 10:e8b66718a103 | 46 | GPIOA->OSPEEDR |= value; |
defrost | 10:e8b66718a103 | 47 | |
defrost | 10:e8b66718a103 | 48 | // Set PWM as outputs to the pins: |
defrost | 10:e8b66718a103 | 49 | value = GPIOA->AFR[1]; |
defrost | 10:e8b66718a103 | 50 | // Reset the lowest four bits: |
defrost | 10:e8b66718a103 | 51 | value &= 0xFFFFFFF0; |
defrost | 10:e8b66718a103 | 52 | // Configure PA_8 to AF: |
defrost | 10:e8b66718a103 | 53 | value |= 0x1; |
defrost | 10:e8b66718a103 | 54 | GPIOA->AFR[1] = value; |
defrost | 10:e8b66718a103 | 55 | |
defrost | 10:e8b66718a103 | 56 | value = GPIOA->AFR[0]; |
defrost | 10:e8b66718a103 | 57 | // Reset the the 4 MSB: |
defrost | 10:e8b66718a103 | 58 | value &= 0x0FFFFFFF; |
defrost | 10:e8b66718a103 | 59 | // Configure PA_7 to AF: |
defrost | 10:e8b66718a103 | 60 | value |= 0x10000000; |
defrost | 10:e8b66718a103 | 61 | GPIOA->AFR[0] = value; |
defrost | 10:e8b66718a103 | 62 | |
defrost | 10:e8b66718a103 | 63 | // Set pull down resistors to PWM outputs: |
defrost | 10:e8b66718a103 | 64 | value = GPIOA->PUPDR; |
defrost | 10:e8b66718a103 | 65 | // Clear the bits: |
defrost | 10:e8b66718a103 | 66 | value &= ~(GPIO_PUPDR_PUPDR7 | GPIO_PUPDR_PUPDR8); |
defrost | 10:e8b66718a103 | 67 | // Set to pull down: |
defrost | 10:e8b66718a103 | 68 | value |= GPIO_PUPDR_PUPDR7_1 | GPIO_PUPDR_PUPDR8_1; |
defrost | 10:e8b66718a103 | 69 | // Set the register: |
defrost | 10:e8b66718a103 | 70 | GPIOA ->PUPDR = value; |
defrost | 10:e8b66718a103 | 71 | |
defrost | 10:e8b66718a103 | 72 | // Set the prescale value to 1: |
defrost | 10:e8b66718a103 | 73 | TIM1->PSC = 0; |
defrost | 10:e8b66718a103 | 74 | |
defrost | 10:e8b66718a103 | 75 | // *** TIM1 control register 1: TIMx_CR1 *** |
defrost | 10:e8b66718a103 | 76 | value = 0; |
defrost | 10:e8b66718a103 | 77 | // [9:8] Set CKD bits to zero for clock division of 1 |
defrost | 10:e8b66718a103 | 78 | // [7] TIMx_ARR register is buffered, set the ARPE bit to 1: |
defrost | 10:e8b66718a103 | 79 | value |= TIM_CR1_ARPE; |
defrost | 10:e8b66718a103 | 80 | // [6:5] Set CMS bits to zero for edge aligned mode |
defrost | 10:e8b66718a103 | 81 | // [6:5] Set CMS bits to 10 for Center Aligned mode 2, up down mode with flags set when counter reaches the top. |
defrost | 10:e8b66718a103 | 82 | //value |= TIM_CR1_CMS_1; |
defrost | 10:e8b66718a103 | 83 | // [4] Set DIR bit to zero for upcounting |
defrost | 10:e8b66718a103 | 84 | // [3] Set OPM bit to zero so that the counter is not stopped at update event |
defrost | 10:e8b66718a103 | 85 | // [2] Set URS bit to zero so that anything can create an interrupt |
defrost | 10:e8b66718a103 | 86 | // [1] Set UDIS bit to zero to generate an update event |
defrost | 10:e8b66718a103 | 87 | // [0] Set the CEN bit to zero to disable the counter |
defrost | 10:e8b66718a103 | 88 | // * Set the TIMx_CR1 Register: * |
defrost | 10:e8b66718a103 | 89 | TIM1->CR1 |= value; |
defrost | 10:e8b66718a103 | 90 | |
defrost | 10:e8b66718a103 | 91 | // *** TIM1 control register 2: TIMx_CR2 *** |
defrost | 10:e8b66718a103 | 92 | value = 0; |
defrost | 10:e8b66718a103 | 93 | // [14] Set OIS4 bit to zero, the idle state of OC4 output |
defrost | 10:e8b66718a103 | 94 | // [13] Set OIS3N bit to zero, the idle state of OC3N output |
defrost | 10:e8b66718a103 | 95 | // [12] Set OIS3 bit to zero, the idle state of OC3 output |
defrost | 10:e8b66718a103 | 96 | // [11] Set OIS2N bit to zero, the idle state of OC2N output |
defrost | 10:e8b66718a103 | 97 | // [10] Set OIS2 bit to zero, the idle state of OC2 output |
defrost | 10:e8b66718a103 | 98 | // [9] Set OIS1N bit to zero, the idle state of OC1N output |
defrost | 10:e8b66718a103 | 99 | // [8] Set OIS1 bit to zero, the idle state of OC1 output |
defrost | 10:e8b66718a103 | 100 | // [7] Set TI1S bit to zero, connecting only CH1 pin to TI1 input |
defrost | 10:e8b66718a103 | 101 | // [6:4] Set to 111: The OC4REF signal is used as trigger output (TRGO) |
defrost | 10:e8b66718a103 | 102 | // value |= TIM_CR2_MMS_2 | TIM_CR2_MMS_1 | TIM_CR2_MMS_0; |
defrost | 10:e8b66718a103 | 103 | //value |= TIM_CR2_MMS_1 | TIM_CR2_MMS_0; |
defrost | 10:e8b66718a103 | 104 | // [3] Set CCDS bit to zero, request sent when CCx event occurs |
defrost | 10:e8b66718a103 | 105 | // [2] Set CCUS bit to 1, capture/compare control bits are updated by setting the COMG bit or when a rising edge occurs on TRGI |
defrost | 10:e8b66718a103 | 106 | //value |= 0x4; |
defrost | 10:e8b66718a103 | 107 | // [0] Set CCPC bit to 1, CCxE, CCxNE and OCxM are update on a commutation event, or rising edge on TRGI |
defrost | 10:e8b66718a103 | 108 | //value |= 0x1; |
defrost | 10:e8b66718a103 | 109 | // * Set the TIMx_CR2 Register: * |
defrost | 10:e8b66718a103 | 110 | TIM1->CR2 = value; |
defrost | 10:e8b66718a103 | 111 | |
defrost | 10:e8b66718a103 | 112 | // *** TIM1 Auto Reload Register: ARR *** |
defrost | 10:e8b66718a103 | 113 | value = 0; |
defrost | 10:e8b66718a103 | 114 | // [15:0] Set ARR bits to the frequency to be loaded in: |
defrost | 10:e8b66718a103 | 115 | newVal = ceil(period_us/PWMSTEP_US); |
defrost | 10:e8b66718a103 | 116 | value = (unsigned int) newVal; |
defrost | 10:e8b66718a103 | 117 | // * Set the TIMx_ARR Register: |
defrost | 10:e8b66718a103 | 118 | TIM1->ARR = value; |
defrost | 10:e8b66718a103 | 119 | |
defrost | 10:e8b66718a103 | 120 | // *** TIM1 capture/compare register 1: CCR1 *** |
defrost | 10:e8b66718a103 | 121 | value = 0; |
defrost | 10:e8b66718a103 | 122 | // [15:0] Set the capture compare value to the duty cycle: |
defrost | 10:e8b66718a103 | 123 | newVal = ceil(duty_us/PWMSTEP_US); |
defrost | 10:e8b66718a103 | 124 | value = (unsigned int) newVal; |
defrost | 10:e8b66718a103 | 125 | // * Set the TIMx_CCR1 Register: |
defrost | 10:e8b66718a103 | 126 | TIM1->CCR1 = value; |
defrost | 10:e8b66718a103 | 127 | |
defrost | 10:e8b66718a103 | 128 | // *** TIM1 capture/compare register 4: CCR4 *** |
defrost | 10:e8b66718a103 | 129 | value = 0; |
defrost | 10:e8b66718a103 | 130 | // [15:0] Set the capture compare value to the value at which the PWM interrupt should be triggered: |
defrost | 10:e8b66718a103 | 131 | newVal = 0; |
defrost | 10:e8b66718a103 | 132 | value = (unsigned int) newVal; |
defrost | 10:e8b66718a103 | 133 | // * Set the TIMx_CCR4 Register: |
defrost | 10:e8b66718a103 | 134 | TIM1->CCR4 = 0; |
defrost | 10:e8b66718a103 | 135 | |
defrost | 10:e8b66718a103 | 136 | // *** TIM1 capture/compare mode register 2: CCMR2 |
defrost | 10:e8b66718a103 | 137 | value = 0; |
defrost | 10:e8b66718a103 | 138 | // [15] Set OC4CE bit to 0, OC4Ref is not affected by the ETRF input |
defrost | 10:e8b66718a103 | 139 | // [14-12] Set the OC4M bits to '110', PWM mode 1, which is what we want I think. |
defrost | 10:e8b66718a103 | 140 | value |= TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4M_1; |
defrost | 10:e8b66718a103 | 141 | // [11] Set the OC4PE bit to 1, meaning read/write operations to the preload event require an update event. |
defrost | 10:e8b66718a103 | 142 | value |= TIM_CCMR2_OC4PE; |
defrost | 10:e8b66718a103 | 143 | // [10] Set the OC4FE bit to 0, the output compare fast enable is disabled |
defrost | 10:e8b66718a103 | 144 | // [9:8] Set the CC4S bits to 0, the channel is configured as an output. |
defrost | 10:e8b66718a103 | 145 | // * Set the TIMx_CCMR2 Register: * |
defrost | 10:e8b66718a103 | 146 | TIM1->CCMR2 = value; |
defrost | 10:e8b66718a103 | 147 | |
defrost | 10:e8b66718a103 | 148 | // *** TIM1 capture/compare mode register 1: CCMR1 |
defrost | 10:e8b66718a103 | 149 | value = 0; |
defrost | 10:e8b66718a103 | 150 | // [7] Set OC1CE bit to 0, OC1Ref is not affected by the ETRF input |
defrost | 10:e8b66718a103 | 151 | // [6-4] Set the OC1M bits to '110', PWM mode 1, which is what we want I think. |
defrost | 10:e8b66718a103 | 152 | value |= TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1; |
defrost | 10:e8b66718a103 | 153 | // [3] Set the OC1PE bit to 1, meaning read/write operations to the preload event require an update event. |
defrost | 10:e8b66718a103 | 154 | value |= TIM_CCMR1_OC1PE; |
defrost | 10:e8b66718a103 | 155 | // [2] Set the OC1FE bit to 0, the output compare fast enable is disabled |
defrost | 10:e8b66718a103 | 156 | // [1:0] Set the CC1S bits to 0, the channel is configured as an output. |
defrost | 10:e8b66718a103 | 157 | // * Set the TIMx_CCMR1 Register: * |
defrost | 10:e8b66718a103 | 158 | TIM1->CCMR1 = value; |
defrost | 10:e8b66718a103 | 159 | |
defrost | 10:e8b66718a103 | 160 | // *** TIM1 capture/compare enable register: CCER |
defrost | 10:e8b66718a103 | 161 | value = 0; |
defrost | 10:e8b66718a103 | 162 | // [15:4] - Don't care: |
defrost | 10:e8b66718a103 | 163 | // [3] Set CC1NP bit to 1 for active low. ( |
defrost | 10:e8b66718a103 | 164 | value |= TIM_CCER_CC1NP; |
defrost | 10:e8b66718a103 | 165 | // [2] Set CC1NE bit to 0, to de-activate the OC1N signal |
defrost | 10:e8b66718a103 | 166 | // value |= 0x4; |
defrost | 10:e8b66718a103 | 167 | // [1] Set the CC1P bit to 1 for active low. |
defrost | 10:e8b66718a103 | 168 | value |= TIM_CCER_CC1P; |
defrost | 10:e8b66718a103 | 169 | // [0] Set the CC1E bit to 1, to de-activate the OC1 signal |
defrost | 10:e8b66718a103 | 170 | // value |= 0x1; |
defrost | 10:e8b66718a103 | 171 | // * Set the TIM1_CCER Register: * |
defrost | 10:e8b66718a103 | 172 | TIM1->CCER = value; |
defrost | 10:e8b66718a103 | 173 | |
defrost | 10:e8b66718a103 | 174 | // *** TIM1 break and dead-time register: BDTR |
defrost | 10:e8b66718a103 | 175 | value = 0; |
defrost | 10:e8b66718a103 | 176 | // [15] Set MOE bit to 1 to enable the OC and OCN outputs |
defrost | 10:e8b66718a103 | 177 | value |= 0x8000; |
defrost | 10:e8b66718a103 | 178 | // [11] Set the OSSR bit such that the ouputs are forced to their idle mode when not running |
defrost | 10:e8b66718a103 | 179 | //value |= TIM_BDTR_OSSR; |
defrost | 10:e8b66718a103 | 180 | // [10] Set OSSI bit such that the outputs are forced to their idle mode when MOE = 0 |
defrost | 10:e8b66718a103 | 181 | value |= TIM_BDTR_OSSI; |
defrost | 10:e8b66718a103 | 182 | // * Set the TIM1_BDTR register: |
defrost | 10:e8b66718a103 | 183 | TIM1->BDTR = value; |
defrost | 10:e8b66718a103 | 184 | |
defrost | 10:e8b66718a103 | 185 | // *** TIM1 DMA/Interrupt enable register: DIER |
defrost | 10:e8b66718a103 | 186 | value = 0; |
defrost | 10:e8b66718a103 | 187 | // [2] Set the CC1IE bit to 1, to trigger an interrupt when counter 1 has a match - which should be half way through the duty cycle. |
defrost | 10:e8b66718a103 | 188 | value |= TIM_DIER_CC4IE; |
defrost | 10:e8b66718a103 | 189 | // Set the TIM1_DIER register: |
defrost | 10:e8b66718a103 | 190 | TIM1->DIER |= value; |
defrost | 10:e8b66718a103 | 191 | |
defrost | 10:e8b66718a103 | 192 | // Set the UG bit in the EGR register to kick things off: |
defrost | 10:e8b66718a103 | 193 | value = 3; |
defrost | 10:e8b66718a103 | 194 | TIM1->EGR = value; |
defrost | 10:e8b66718a103 | 195 | |
defrost | 10:e8b66718a103 | 196 | // Print a message saying you are done: |
defrost | 10:e8b66718a103 | 197 | INFO("PWM configuration complete!"); |
defrost | 10:e8b66718a103 | 198 | |
defrost | 10:e8b66718a103 | 199 | #ifdef DEBUG_PWM |
defrost | 10:e8b66718a103 | 200 | // Debugging Code: |
defrost | 10:e8b66718a103 | 201 | DBG("TIM1 Registers:"); |
defrost | 10:e8b66718a103 | 202 | DBG("The CCMR1 Register reads: %d", TIM1->CCMR1); |
defrost | 10:e8b66718a103 | 203 | DBG("The CR1 Register reads: %d", TIM1->CR1); |
defrost | 10:e8b66718a103 | 204 | DBG("The CR2 Register reads: %d", TIM1->CR2); |
defrost | 10:e8b66718a103 | 205 | DBG("The ARR Register reads: %d", TIM1->ARR); |
defrost | 10:e8b66718a103 | 206 | DBG("The CCR1 Register reads: %d", TIM1->CCR1); |
defrost | 10:e8b66718a103 | 207 | DBG("The CCER Register reads: %d", TIM1->CCER); |
defrost | 10:e8b66718a103 | 208 | DBG("The BDTR Register reads: %d", TIM1->BDTR); |
defrost | 10:e8b66718a103 | 209 | DBG("The EGR Register reads: %d", TIM1->EGR); |
defrost | 10:e8b66718a103 | 210 | DBG("The SMCR Register reads: %d", TIM1->SMCR); |
defrost | 10:e8b66718a103 | 211 | DBG("The PSC Register reads: %d", TIM1->PSC); |
defrost | 10:e8b66718a103 | 212 | DBG("The GPIOA Registers:\n\r"); |
defrost | 10:e8b66718a103 | 213 | DBG("The MODER Register reads: %d", GPIOA->MODER); |
defrost | 10:e8b66718a103 | 214 | DBG("The OSPEEDR Register reads: %d", GPIOA->OSPEEDR); |
defrost | 10:e8b66718a103 | 215 | DBG("The AFR[0] Register reads: %d", GPIOA->AFR[0]); |
defrost | 10:e8b66718a103 | 216 | DBG("The AFR[1] Register reads: %d", GPIOA->AFR[1]); |
defrost | 10:e8b66718a103 | 217 | DBG("Clock Registers:"); |
defrost | 10:e8b66718a103 | 218 | DBG("The CFGR Register reads: %d", RCC->CFGR); |
defrost | 10:e8b66718a103 | 219 | |
defrost | 10:e8b66718a103 | 220 | #endif |
defrost | 10:e8b66718a103 | 221 | |
defrost | 10:e8b66718a103 | 222 | INFO("TIM1 Interrupt Priority: %d", NVIC_GetPriority(TIM1_CC_IRQn)); |
defrost | 10:e8b66718a103 | 223 | INFO("UART1 Interrupt Priority: %d", NVIC_GetPriority(USART1_IRQn)); |
defrost | 10:e8b66718a103 | 224 | INFO("UART2 Interrupt Priority: %d", NVIC_GetPriority(USART2_IRQn)); |
defrost | 10:e8b66718a103 | 225 | INFO("UART6 Interrupt Priority: %d", NVIC_GetPriority(USART6_IRQn)); |
defrost | 10:e8b66718a103 | 226 | |
defrost | 10:e8b66718a103 | 227 | // Configure the interrupt: |
defrost | 10:e8b66718a103 | 228 | NVIC_SetVector(TIM1_CC_IRQn, (uint32_t)&TIM1_CC_IRQHandler); |
defrost | 10:e8b66718a103 | 229 | NVIC_SetPriority(TIM1_CC_IRQn, PWMHIGHPRIORITY); |
defrost | 10:e8b66718a103 | 230 | NVIC_EnableIRQ(TIM1_CC_IRQn); |
defrost | 10:e8b66718a103 | 231 | |
defrost | 10:e8b66718a103 | 232 | |
defrost | 10:e8b66718a103 | 233 | |
defrost | 10:e8b66718a103 | 234 | return; |
defrost | 10:e8b66718a103 | 235 | } |
defrost | 10:e8b66718a103 | 236 | |
defrost | 10:e8b66718a103 | 237 | void TIM1_CC_IRQHandler(void){ |
defrost | 10:e8b66718a103 | 238 | |
defrost | 10:e8b66718a103 | 239 | // States of the PWM module: |
defrost | 10:e8b66718a103 | 240 | /* |
defrost | 10:e8b66718a103 | 241 | #define PWMST_SETUPCONV 0 |
defrost | 10:e8b66718a103 | 242 | #define PWMST_STARTCONV 1 |
defrost | 10:e8b66718a103 | 243 | #define PWMST_RUNSCSKDC 2 |
defrost | 10:e8b66718a103 | 244 | #define PWMST_CALCNEWPH 3 |
defrost | 10:e8b66718a103 | 245 | #define PWMST_SETNEWPH 4 |
defrost | 10:e8b66718a103 | 246 | #define PWMST_SHIFT 5 |
defrost | 10:e8b66718a103 | 247 | #define PWMST_SAMPLECHTROUGH 6 |
defrost | 10:e8b66718a103 | 248 | #define PWMST_WAITSAMPLETROUGH 7 |
defrost | 10:e8b66718a103 | 249 | #define PWMST_WAIT 8 |
defrost | 10:e8b66718a103 | 250 | #define PWMST_SAMPLECHHILL 9 |
defrost | 10:e8b66718a103 | 251 | #define PWMST_WAITSAMPLEHILL 10 |
defrost | 10:e8b66718a103 | 252 | #define PWMST_MAXST 11 |
defrost | 10:e8b66718a103 | 253 | */ |
defrost | 10:e8b66718a103 | 254 | |
defrost | 10:e8b66718a103 | 255 | if(((TIM1->SR & TIM_SR_CC4IF) > 0)&&(IotStatus.CheckFlag(SS_PWMOVERRUNFLAG) == false)){ |
defrost | 10:e8b66718a103 | 256 | // Block any other interrupts from occuring: |
defrost | 10:e8b66718a103 | 257 | IotStatus.SetFlag(SS_PWMOVERRUNFLAG); |
defrost | 10:e8b66718a103 | 258 | |
defrost | 10:e8b66718a103 | 259 | db = 1; |
defrost | 10:e8b66718a103 | 260 | |
defrost | 10:e8b66718a103 | 261 | // Sample the ADCs: |
defrost | 10:e8b66718a103 | 262 | VoltageMeasurement = VoltageSensor.read(); |
defrost | 10:e8b66718a103 | 263 | CurrentMeasurement = CurrentSensor.read(); |
defrost | 10:e8b66718a103 | 264 | db = 0; |
defrost | 10:e8b66718a103 | 265 | // Set battery model inputs: |
defrost | 10:e8b66718a103 | 266 | |
defrost | 10:e8b66718a103 | 267 | |
defrost | 10:e8b66718a103 | 268 | // Set a debug pin high: |
defrost | 10:e8b66718a103 | 269 | db = 1; // Probe this pin to see how long the battery model algorithm takes to run. |
defrost | 10:e8b66718a103 | 270 | |
defrost | 10:e8b66718a103 | 271 | // Run battery model here: |
defrost | 10:e8b66718a103 | 272 | |
defrost | 10:e8b66718a103 | 273 | |
defrost | 10:e8b66718a103 | 274 | // Clear the debug pin: |
defrost | 10:e8b66718a103 | 275 | db = 0; |
defrost | 10:e8b66718a103 | 276 | |
defrost | 10:e8b66718a103 | 277 | // Read battery model outputs: |
defrost | 10:e8b66718a103 | 278 | |
defrost | 10:e8b66718a103 | 279 | |
defrost | 10:e8b66718a103 | 280 | |
defrost | 10:e8b66718a103 | 281 | // Clear the flag: |
defrost | 10:e8b66718a103 | 282 | IotStatus.ClearFlag(SS_PWMOVERRUNFLAG); |
defrost | 10:e8b66718a103 | 283 | TIM1->SR &= (~TIM_SR_CC4IF); |
defrost | 10:e8b66718a103 | 284 | } |
defrost | 10:e8b66718a103 | 285 | |
defrost | 10:e8b66718a103 | 286 | |
defrost | 10:e8b66718a103 | 287 | return; |
defrost | 10:e8b66718a103 | 288 | } |
defrost | 10:e8b66718a103 | 289 | |
defrost | 10:e8b66718a103 | 290 | |
defrost | 10:e8b66718a103 | 291 | |
defrost | 10:e8b66718a103 | 292 | |
defrost | 10:e8b66718a103 | 293 | |
defrost | 10:e8b66718a103 | 294 | // Set a new duty cycle: |
defrost | 10:e8b66718a103 | 295 | float SetDuty_us(float duty_us){ |
defrost | 10:e8b66718a103 | 296 | unsigned int value; |
defrost | 10:e8b66718a103 | 297 | float newVal; |
defrost | 10:e8b66718a103 | 298 | float temp = (duty_us/PwmPeriod_us); |
defrost | 10:e8b66718a103 | 299 | |
defrost | 10:e8b66718a103 | 300 | newVal = ceil(duty_us/PWMSTEP_US); |
defrost | 10:e8b66718a103 | 301 | value = (unsigned int) newVal; |
defrost | 10:e8b66718a103 | 302 | // Disable the Update Event: |
defrost | 10:e8b66718a103 | 303 | SETUDIS; |
defrost | 10:e8b66718a103 | 304 | // * Set the TIMx_CCR1 Register: |
defrost | 10:e8b66718a103 | 305 | TIM1->CCR1 = value; |
defrost | 10:e8b66718a103 | 306 | // Set the CCR4 Register to the maximum value minus CH4SHIFT. This ensures the high speed ADC is in sync with the PWM module. |
defrost | 10:e8b66718a103 | 307 | TIM1->CCR4 = 0; |
defrost | 10:e8b66718a103 | 308 | // Re-enable the update event |
defrost | 10:e8b66718a103 | 309 | CLEARUDIS; |
defrost | 10:e8b66718a103 | 310 | return temp*PwmPeriod_us; |
defrost | 10:e8b66718a103 | 311 | } |
defrost | 10:e8b66718a103 | 312 | |
defrost | 10:e8b66718a103 | 313 | |
defrost | 10:e8b66718a103 | 314 | // Turns on and off the PWM: |
defrost | 10:e8b66718a103 | 315 | void TurnOnPWM(bool trueForOn){ |
defrost | 10:e8b66718a103 | 316 | if(trueForOn){ |
defrost | 10:e8b66718a103 | 317 | // Enable the outputs: |
defrost | 10:e8b66718a103 | 318 | DBG("Enabling outputs..."); |
defrost | 10:e8b66718a103 | 319 | TIM1->CCER |= TIM_CCER_CC1E | TIM_CCER_CC1NE; |
defrost | 10:e8b66718a103 | 320 | // Turn on the gating: |
defrost | 10:e8b66718a103 | 321 | DBG("Turning on gating...:"); |
defrost | 10:e8b66718a103 | 322 | TIM1->CR1 |= TIM_CR1_CEN; |
defrost | 10:e8b66718a103 | 323 | DBG("PWM on."); |
defrost | 10:e8b66718a103 | 324 | |
defrost | 10:e8b66718a103 | 325 | }else{ |
defrost | 10:e8b66718a103 | 326 | // Turn off the gating: |
defrost | 10:e8b66718a103 | 327 | TIM1->CR1 &= ~TIM_CR1_CEN; |
defrost | 10:e8b66718a103 | 328 | // Disable the outputs: |
defrost | 10:e8b66718a103 | 329 | TIM1->CCER &= ~(TIM_CCER_CC1E | TIM_CCER_CC1NE); |
defrost | 10:e8b66718a103 | 330 | } |
defrost | 10:e8b66718a103 | 331 | return; |
defrost | 10:e8b66718a103 | 332 | } |
defrost | 10:e8b66718a103 | 333 | |
defrost | 10:e8b66718a103 | 334 | |
defrost | 10:e8b66718a103 | 335 | |
defrost | 10:e8b66718a103 | 336 | void SetPWMPeriodAndDuty(int pwmper){ |
defrost | 10:e8b66718a103 | 337 | // This functions sets the PWM period by first disabling updates to the PWM module |
defrost | 10:e8b66718a103 | 338 | // It also scales the duty cycle register, so the duty cycle is the SAME. |
defrost | 10:e8b66718a103 | 339 | |
defrost | 10:e8b66718a103 | 340 | // Disable the UEV event in the PWM module: |
defrost | 10:e8b66718a103 | 341 | SETUDIS; |
defrost | 10:e8b66718a103 | 342 | // Set the new period: |
defrost | 10:e8b66718a103 | 343 | TIM1->ARR = (unsigned int)(PwmPeriod_us/PWMSTEP_US); |
defrost | 10:e8b66718a103 | 344 | // Set the new duty cycle: |
defrost | 10:e8b66718a103 | 345 | TIM1->CCR1 = ((unsigned int)(Duty_us/PwmPeriod_us * TIM1->ARR)); |
defrost | 10:e8b66718a103 | 346 | // Set the CCR4 Register to the maximum value minus CH4SHIFT. This ensures the high speed ADC is in sync with the PWM module. |
defrost | 10:e8b66718a103 | 347 | TIM1->CCR4 = 0; |
defrost | 10:e8b66718a103 | 348 | // Re-enable the UEV event: |
defrost | 10:e8b66718a103 | 349 | CLEARUDIS; |
defrost | 10:e8b66718a103 | 350 | // Done! |
defrost | 10:e8b66718a103 | 351 | return; |
defrost | 10:e8b66718a103 | 352 | } |
defrost | 10:e8b66718a103 | 353 | |
defrost | 10:e8b66718a103 | 354 | void SetPWMPeriodAndDuty_us(float period){ |
defrost | 10:e8b66718a103 | 355 | // This functions sets the PWM period by first disabling updates to the PWM module |
defrost | 10:e8b66718a103 | 356 | // It also scales the duty cycle register, so the duty cycle is the SAME. |
defrost | 10:e8b66718a103 | 357 | float PwmSteps = ((float)period/(float)PWMSTEP_US); |
defrost | 10:e8b66718a103 | 358 | |
defrost | 10:e8b66718a103 | 359 | // Disable the UEV event in the PWM module: |
defrost | 10:e8b66718a103 | 360 | SETUDIS; |
defrost | 10:e8b66718a103 | 361 | // Set the new period: |
defrost | 10:e8b66718a103 | 362 | if(PwmSteps > PWMARRMAX){ |
defrost | 10:e8b66718a103 | 363 | PwmSteps = PWMARRMAX; |
defrost | 10:e8b66718a103 | 364 | WARN("Maximum PWM Period Reached."); |
defrost | 10:e8b66718a103 | 365 | } |
defrost | 10:e8b66718a103 | 366 | TIM1->ARR = (unsigned int)(PwmSteps); |
defrost | 10:e8b66718a103 | 367 | DBG("TIM1->ARR: %d", TIM1->ARR); |
defrost | 10:e8b66718a103 | 368 | DBG("period: %.3f", period); |
defrost | 10:e8b66718a103 | 369 | DBG("PWMSTEP: %.3f", (float) PWMSTEP_US); |
defrost | 10:e8b66718a103 | 370 | // Set the new duty cycle: |
defrost | 10:e8b66718a103 | 371 | TIM1->CCR1 = ((unsigned int)(Duty_us/period * TIM1->ARR)); |
defrost | 10:e8b66718a103 | 372 | // Set the CCR4 Register to the maximum value minus CH4SHIFT. This ensures the high speed ADC is in sync with the PWM module. |
defrost | 10:e8b66718a103 | 373 | TIM1->CCR4 = 0; |
defrost | 10:e8b66718a103 | 374 | // Re-enable the UEV event: |
defrost | 10:e8b66718a103 | 375 | CLEARUDIS; |
defrost | 10:e8b66718a103 | 376 | // Done! |
defrost | 10:e8b66718a103 | 377 | return; |
defrost | 10:e8b66718a103 | 378 | } |
defrost | 10:e8b66718a103 | 379 | |
defrost | 10:e8b66718a103 | 380 |