├── LICENSE ├── README.md ├── svpwm.c └── svpwm.h /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 xxJian 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # STM32_Based_SVPWM 2 | SpaceVector PWM for Three-phase H-birdge Inverter Driving a Blushless DC Motor 3 | It's written in C. 4 | Project is generated with STM32CubeMX. 5 | 6 | Revision history: 7 | 1. Oct. 10th, 2018. Files created. But it has not been tested. 8 | 9 | Hardware: 10 | 1. STM32F103C8 based evaluation board or development board 11 | 2. Three phase H bridge inverter with essential driver(optional) 12 | 3. a BLDC(optional) 13 | 14 | Software(Environment): 15 | 1. Atollic TrueSTUDIO for STM32(recommended) 16 | 2. STM32CubeMX v4.26.0 17 | 3. STM32CubeF1 Firmware Package V1.6.0 18 | -------------------------------------------------------------------------------- /svpwm.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "svpwm.h" 4 | #include "math.h" 5 | 6 | #define PI 3.1416 7 | 8 | BLDC_SVPWMTypeDef svpwm1; 9 | 10 | 11 | void Clark_Transformation(float* In_a, float* In_b, float* In_c, float* Out_alpha, float* Out_beta) 12 | { 13 | (*Out_alpha) = (*In_a)*0.6667 - (*In_b)*0.3333 - (*In_c)*0.3333; 14 | (*Out_beta) = ((*In_b) - (*In_c)) * 0.5774; 15 | } 16 | void InvClark_Transformation(float* In_alpha, float* In_beta, float* Out_a, float* Out_b, float* Out_c) 17 | { 18 | (*Out_a) = (*In_alpha); 19 | (*Out_b) = -0.5 * (*In_alpha) + 0.8660 * (*In_beta); 20 | (*Out_c) = -0.5 * (*In_alpha) - 0.8660 * (*In_beta); 21 | } 22 | void sectorJudge(BLDC_SVPWMTypeDef* svpwm) 23 | { 24 | svpwm->b_VrefAngle = atan2(svpwm->b_VrefBeta, svpwm->b_VrefAlpha); 25 | 26 | if(( svpwm->b_VrefAngle >= 0.0) && ( svpwm->b_VrefAngle < PI/3.0)) 27 | { 28 | svpwm->b_sector = 1; 29 | } 30 | else if(( svpwm->b_VrefAngle >= PI/3.0) && ( svpwm->b_VrefAngle < 2.0*PI/3.0)) 31 | { 32 | svpwm->b_sector = 2; 33 | } 34 | else if(( svpwm->b_VrefAngle >= 2.0*PI/3.0) && ( svpwm->b_VrefAngle < PI)) 35 | { 36 | svpwm->b_sector = 3; 37 | } 38 | else if(( svpwm->b_VrefAngle >= -PI/3.0) && ( svpwm->b_VrefAngle < 0.0)) 39 | { 40 | svpwm->b_sector = 6; 41 | } 42 | else if(( svpwm->b_VrefAngle >= -2.0*PI/3.0) && ( svpwm->b_VrefAngle < -PI/3.0)) 43 | { 44 | svpwm->b_sector = 5; 45 | } 46 | else if(( svpwm->b_VrefAngle >= -PI) && ( svpwm->b_VrefAngle < -2.0*PI/3.0)) 47 | { 48 | svpwm->b_sector = 4; 49 | } 50 | else 51 | { 52 | while(1); //computation error 53 | } 54 | } 55 | int32_t sectorJudge_v2(BLDC_SVPWMTypeDef* svpwm) 56 | { 57 | float U1,U2,U3; 58 | int32_t A,B,C,N,b_sector1; 59 | 60 | U1 = svpwm->b_VrefBeta; 61 | U2 = 0.8660*svpwm->b_VrefAlpha - svpwm->b_VrefBeta*0.5; 62 | U3 = -0.8660*svpwm->b_VrefAlpha - svpwm->b_VrefBeta*0.5; 63 | 64 | if(U1>0) { 65 | A=1; 66 | } 67 | else { 68 | A=0; 69 | } 70 | if(U2>0) { 71 | B=1; 72 | } 73 | else { 74 | B=0; 75 | } 76 | if(U3>0) { 77 | C=1; 78 | } 79 | else { 80 | C=0; 81 | } 82 | 83 | N = 4*C +2*B +A; 84 | if( N==3) { 85 | b_sector1 = 1; 86 | } 87 | else if( N==1){ 88 | b_sector1 = 2; 89 | } 90 | else if( N==5) { 91 | b_sector1 = 3; 92 | } 93 | else if( N==4) { 94 | b_sector1 = 4; 95 | } 96 | else if (N==6) { 97 | b_sector1 = 5; 98 | } 99 | else if( N==2) { 100 | b_sector1 = 6; 101 | } 102 | return b_sector1; 103 | } 104 | void SpaceVectorUpdate(BLDC_SVPWMTypeDef* svpwm) 105 | { 106 | switch(svpwm->b_sector) 107 | { 108 | case 1: 109 | svpwm->a_VectorOut[0] = 4; 110 | svpwm->a_VectorOut[1] = 6; 111 | svpwm->a_VectorOut[2] = 0; 112 | 113 | svpwm->a_VectorOutDuty[0] = svpwm->b_VrefAlpha - svpwm->b_VrefBeta*0.57735; 114 | svpwm->a_VectorOutDuty[1] = svpwm->b_VrefBeta*1.1547; 115 | svpwm->a_VectorOutDuty[2] = 0; 116 | break; 117 | case 2: 118 | svpwm->a_VectorOut[0] = 2; 119 | svpwm->a_VectorOut[1] = 6; 120 | svpwm->a_VectorOut[2] = 0; 121 | 122 | svpwm->a_VectorOutDuty[0] = -svpwm->b_VrefAlpha + svpwm->b_VrefBeta*0.57735; 123 | svpwm->a_VectorOutDuty[1] = svpwm->b_VrefAlpha + svpwm->b_VrefBeta*0.57735; 124 | svpwm->a_VectorOutDuty[2] = 0; 125 | break; 126 | case 3: 127 | svpwm->a_VectorOut[0] = 2; 128 | svpwm->a_VectorOut[1] = 3; 129 | svpwm->a_VectorOut[2] = 0; 130 | 131 | svpwm->a_VectorOutDuty[0] = svpwm->b_VrefBeta*1.1547; 132 | svpwm->a_VectorOutDuty[1] = -svpwm->b_VrefAlpha - svpwm->b_VrefBeta*0.57735; 133 | svpwm->a_VectorOutDuty[2] = 0; 134 | break; 135 | case 4: 136 | svpwm->a_VectorOut[0] = 1; 137 | svpwm->a_VectorOut[1] = 3; 138 | svpwm->a_VectorOut[2] = 0; 139 | 140 | svpwm->a_VectorOutDuty[0] = -svpwm->b_VrefBeta*1.1547; 141 | svpwm->a_VectorOutDuty[1] = -svpwm->b_VrefAlpha + svpwm->b_VrefBeta*0.57735; 142 | svpwm->a_VectorOutDuty[2] = 0; 143 | break; 144 | case 5: 145 | 146 | svpwm->a_VectorOut[0] = 1; 147 | svpwm->a_VectorOut[1] = 5; 148 | svpwm->a_VectorOut[2] = 0; 149 | 150 | svpwm->a_VectorOutDuty[0] = -svpwm->b_VrefAlpha - svpwm->b_VrefBeta*0.57735; 151 | svpwm->a_VectorOutDuty[1] = svpwm->b_VrefAlpha - svpwm->b_VrefBeta*0.57735; 152 | svpwm->a_VectorOutDuty[2] = 0; 153 | break; 154 | case 6: 155 | 156 | svpwm->a_VectorOut[0] = 4; 157 | svpwm->a_VectorOut[1] = 5; 158 | svpwm->a_VectorOut[2] = 0; 159 | 160 | svpwm->a_VectorOutDuty[0] = svpwm->b_VrefAlpha + svpwm->b_VrefBeta*0.57735; 161 | svpwm->a_VectorOutDuty[1] = -svpwm->b_VrefBeta*1.1547; 162 | svpwm->a_VectorOutDuty[2] = 1.0- svpwm->a_VectorOutDuty[0] - svpwm->a_VectorOutDuty[1]; 163 | break; 164 | default: 165 | break; 166 | } 167 | 168 | svpwm->a_VectorOutDutyCmpr[0] = svpwm->a_VectorOutDuty[2] * 14399/2.0; 169 | svpwm->a_VectorOutDutyCmpr[1] = svpwm->a_VectorOutDuty[0] * 14399/2.0; 170 | svpwm->a_VectorOutDutyCmpr[2] = svpwm->a_VectorOutDuty[1] * 14399; 171 | svpwm->a_VectorOutDutyCmpr[3] = svpwm->a_VectorOutDuty[0] * 14399/2.0; 172 | 173 | svpwm->a_VectorOutDutyCmpr[1] += svpwm->a_VectorOutDutyCmpr[0]; 174 | svpwm->a_VectorOutDutyCmpr[2] += svpwm->a_VectorOutDutyCmpr[1]; 175 | svpwm->a_VectorOutDutyCmpr[3] += svpwm->a_VectorOutDutyCmpr[2]; 176 | 177 | } 178 | void TIM1CmprLoad(void) 179 | { 180 | __HAL_TIM_SET_COMPARE(htim1, TIM_CHANNEL_1, svpwm1.a_VectorOutDutyCmpr[0]); 181 | __HAL_TIM_SET_COMPARE(htim1, TIM_CHANNEL_2, svpwm1.a_VectorOutDutyCmpr[1]); 182 | __HAL_TIM_SET_COMPARE(htim1, TIM_CHANNEL_3, svpwm1.a_VectorOutDutyCmpr[2]); 183 | __HAL_TIM_SET_COMPARE(htim1, TIM_CHANNEL_4, svpwm1.a_VectorOutDutyCmpr[3]); 184 | 185 | } 186 | void SVPWM1_SpaceVectorDRV(uint8_t spaceVectorOut) 187 | { 188 | if(spaceVectorOut==0) 189 | { // 000 190 | HAL_GPIO_WritePin(BLDC_UH_GPIO_Port, BLDC_UH_Pin, GPIO_PIN_RESET); 191 | HAL_GPIO_WritePin(BLDC_VH_GPIO_Port, BLDC_VH_Pin, GPIO_PIN_RESET); 192 | HAL_GPIO_WritePin(BLDC_WH_GPIO_Port, BLDC_WH_Pin, GPIO_PIN_RESET); 193 | 194 | HAL_GPIO_WritePin(BLDC_UL_GPIO_Port, BLDC_UL_Pin, GPIO_PIN_SET); 195 | HAL_GPIO_WritePin(BLDC_VL_GPIO_Port, BLDC_VL_Pin, GPIO_PIN_SET); 196 | HAL_GPIO_WritePin(BLDC_WL_GPIO_Port, BLDC_WL_Pin, GPIO_PIN_SET); 197 | } 198 | else if(spaceVectorOut==1) 199 | { // 001 200 | HAL_GPIO_WritePin(BLDC_UH_GPIO_Port, BLDC_UH_Pin, GPIO_PIN_RESET); 201 | HAL_GPIO_WritePin(BLDC_VH_GPIO_Port, BLDC_VH_Pin, GPIO_PIN_RESET); 202 | HAL_GPIO_WritePin(BLDC_WL_GPIO_Port, BLDC_WL_Pin, GPIO_PIN_RESET); 203 | 204 | HAL_GPIO_WritePin(BLDC_UL_GPIO_Port, BLDC_UL_Pin, GPIO_PIN_SET); 205 | HAL_GPIO_WritePin(BLDC_VL_GPIO_Port, BLDC_VL_Pin, GPIO_PIN_SET); 206 | HAL_GPIO_WritePin(BLDC_WH_GPIO_Port, BLDC_WH_Pin, GPIO_PIN_SET); 207 | } 208 | else if(spaceVectorOut==2) 209 | { // 010 210 | HAL_GPIO_WritePin(BLDC_UH_GPIO_Port, BLDC_UH_Pin, GPIO_PIN_RESET); 211 | HAL_GPIO_WritePin(BLDC_VL_GPIO_Port, BLDC_VL_Pin, GPIO_PIN_RESET); 212 | HAL_GPIO_WritePin(BLDC_WH_GPIO_Port, BLDC_WH_Pin, GPIO_PIN_RESET); 213 | 214 | HAL_GPIO_WritePin(BLDC_UL_GPIO_Port, BLDC_UL_Pin, GPIO_PIN_SET); 215 | HAL_GPIO_WritePin(BLDC_VH_GPIO_Port, BLDC_VH_Pin, GPIO_PIN_SET); 216 | HAL_GPIO_WritePin(BLDC_WL_GPIO_Port, BLDC_WL_Pin, GPIO_PIN_SET); 217 | } 218 | else if(spaceVectorOut==3) 219 | { // 011 220 | HAL_GPIO_WritePin(BLDC_UH_GPIO_Port, BLDC_UH_Pin, GPIO_PIN_RESET); 221 | HAL_GPIO_WritePin(BLDC_VL_GPIO_Port, BLDC_VL_Pin, GPIO_PIN_RESET); 222 | HAL_GPIO_WritePin(BLDC_WL_GPIO_Port, BLDC_WL_Pin, GPIO_PIN_RESET); 223 | 224 | HAL_GPIO_WritePin(BLDC_UL_GPIO_Port, BLDC_UL_Pin, GPIO_PIN_SET); 225 | HAL_GPIO_WritePin(BLDC_VH_GPIO_Port, BLDC_VH_Pin, GPIO_PIN_SET); 226 | HAL_GPIO_WritePin(BLDC_WH_GPIO_Port, BLDC_WH_Pin, GPIO_PIN_SET); 227 | } 228 | else if(spaceVectorOut==4) 229 | { // 100 230 | HAL_GPIO_WritePin(BLDC_UL_GPIO_Port, BLDC_UL_Pin, GPIO_PIN_RESET); 231 | HAL_GPIO_WritePin(BLDC_VH_GPIO_Port, BLDC_VH_Pin, GPIO_PIN_RESET); 232 | HAL_GPIO_WritePin(BLDC_WH_GPIO_Port, BLDC_WH_Pin, GPIO_PIN_RESET); 233 | 234 | HAL_GPIO_WritePin(BLDC_UH_GPIO_Port, BLDC_UH_Pin, GPIO_PIN_SET); 235 | HAL_GPIO_WritePin(BLDC_VL_GPIO_Port, BLDC_VL_Pin, GPIO_PIN_SET); 236 | HAL_GPIO_WritePin(BLDC_WL_GPIO_Port, BLDC_WL_Pin, GPIO_PIN_SET); 237 | } 238 | else if(spaceVectorOut==5) 239 | { // 101 240 | HAL_GPIO_WritePin(BLDC_UL_GPIO_Port, BLDC_UL_Pin, GPIO_PIN_RESET); 241 | HAL_GPIO_WritePin(BLDC_VH_GPIO_Port, BLDC_VH_Pin, GPIO_PIN_RESET); 242 | HAL_GPIO_WritePin(BLDC_WL_GPIO_Port, BLDC_WL_Pin, GPIO_PIN_RESET); 243 | 244 | HAL_GPIO_WritePin(BLDC_UH_GPIO_Port, BLDC_UH_Pin, GPIO_PIN_SET); 245 | HAL_GPIO_WritePin(BLDC_VL_GPIO_Port, BLDC_VL_Pin, GPIO_PIN_SET); 246 | HAL_GPIO_WritePin(BLDC_WH_GPIO_Port, BLDC_WH_Pin, GPIO_PIN_SET); 247 | } 248 | else if(spaceVectorOut==6) 249 | { // 110 250 | HAL_GPIO_WritePin(BLDC_UL_GPIO_Port, BLDC_UL_Pin, GPIO_PIN_RESET); 251 | HAL_GPIO_WritePin(BLDC_VL_GPIO_Port, BLDC_VL_Pin, GPIO_PIN_RESET); 252 | HAL_GPIO_WritePin(BLDC_WH_GPIO_Port, BLDC_WH_Pin, GPIO_PIN_RESET); 253 | 254 | HAL_GPIO_WritePin(BLDC_UH_GPIO_Port, BLDC_UH_Pin, GPIO_PIN_SET); 255 | HAL_GPIO_WritePin(BLDC_VH_GPIO_Port, BLDC_VH_Pin, GPIO_PIN_SET); 256 | HAL_GPIO_WritePin(BLDC_WL_GPIO_Port, BLDC_WL_Pin, GPIO_PIN_SET); 257 | } 258 | else if(spaceVectorOut==7) 259 | { // 111 260 | HAL_GPIO_WritePin(BLDC_UL_GPIO_Port, BLDC_UL_Pin, GPIO_PIN_RESET); 261 | HAL_GPIO_WritePin(BLDC_VL_GPIO_Port, BLDC_VL_Pin, GPIO_PIN_RESET); 262 | HAL_GPIO_WritePin(BLDC_WL_GPIO_Port, BLDC_WL_Pin, GPIO_PIN_RESET); 263 | 264 | HAL_GPIO_WritePin(BLDC_UH_GPIO_Port, BLDC_UH_Pin, GPIO_PIN_SET); 265 | HAL_GPIO_WritePin(BLDC_VH_GPIO_Port, BLDC_VH_Pin, GPIO_PIN_SET); 266 | HAL_GPIO_WritePin(BLDC_WH_GPIO_Port, BLDC_WH_Pin, GPIO_PIN_SET); 267 | } 268 | } 269 | void SVPWM1_SpaceVectorDRV_v2(uint8_t spaceVectorOut) 270 | { 271 | 272 | uint32_t tmpccmrx = 0U; 273 | 274 | 275 | // 更新本次的空间矢量 276 | HAL_TIM_GenerateEvent(htim1, TIM_EVENTSOURCE_COM); 277 | 278 | 279 | // 装载下次需要发出的空间矢量 280 | // CCxE CCxNE OCxM 281 | // OC1M OC2M in CCMR1 OC3M OC4M in CCMR2 282 | if(spaceVectorOut==0) 283 | { // 000 284 | //OCxM 285 | /* Get the TIMx CCMR1 register value */ 286 | tmpccmrx = TIMx->CCMR1; 287 | /* Reset the Output Compare Mode Bits */ 288 | tmpccmrx &= ~TIM_CCMR1_OC1M; 289 | tmpccmrx &= ~TIM_CCMR1_OC2M; 290 | /* Select the Output Compare Mode */ 291 | tmpccmrx |= TIM_OCMODE_INACTIVE; 292 | tmpccmrx |= (TIM_OCMODE_INACTIVE << 8U); 293 | 294 | /* Write to TIMx CCMR1 */ 295 | htim1.CCMR1 = tmpccmrx; 296 | 297 | tmpccmrx = TIMx->CCMR2; 298 | tmpccmrx &= ~TIM_CCMR2_OC3M; 299 | tmpccmrx |= TIM_OCMODE_INACTIVE; 300 | htim1.CCMR2 = tmpccmrx; 301 | 302 | htim1.CCER &= ~TIM_CCER_CC1E; //CC1E=0 303 | htim1.CCER |= TIM_CCER_CC1NE; //CC1NE=1 304 | htim1.CCER &= ~TIM_CCER_CC2E; //CC2E=0 305 | htim1.CCER |= TIM_CCER_CC2NE; //CC2NE=1 306 | htim1.CCER &= ~TIM_CCER_CC3E; //CC3E=0 307 | htim1.CCER |= TIM_CCER_CC3NE; //CC3NE=1 308 | } 309 | else if(spaceVectorOut==1) 310 | { // 001 311 | //OC1M OC2M 312 | tmpccmrx = TIMx->CCMR1; 313 | tmpccmrx &= ~TIM_CCMR1_OC1M; 314 | tmpccmrx &= ~TIM_CCMR1_OC2M; 315 | tmpccmrx |= TIM_OCMODE_INACTIVE; 316 | tmpccmrx |= (TIM_OCMODE_INACTIVE << 8U); 317 | htim1.CCMR1 = tmpccmrx; 318 | 319 | //OC3M 320 | tmpccmrx = TIMx->CCMR2; 321 | tmpccmrx &= ~TIM_CCMR2_OC3M; 322 | tmpccmrx |= TIM_OCMODE_ACTIVE; 323 | htim1.CCMR2 = tmpccmrx; 324 | 325 | htim1.CCER &= ~TIM_CCER_CC1E; //CC1E=0 326 | htim1.CCER |= TIM_CCER_CC1NE; //CC1NE=1 327 | htim1.CCER &= ~TIM_CCER_CC2E; //CC2E=0 328 | htim1.CCER |= TIM_CCER_CC2NE; //CC2NE=1 329 | htim1.CCER |= TIM_CCER_CC3E; //CC3E=1 330 | htim1.CCER &= ~TIM_CCER_CC3NE; //CC3NE=0 331 | } 332 | else if(spaceVectorOut==2) 333 | { // 010 334 | //OC1M OC2M 335 | tmpccmrx = TIMx->CCMR1; 336 | tmpccmrx &= ~TIM_CCMR1_OC1M; 337 | tmpccmrx &= ~TIM_CCMR1_OC2M; 338 | tmpccmrx |= TIM_OCMODE_INACTIVE; 339 | tmpccmrx |= (TIM_OCMODE_ACTIVE << 8U); 340 | htim1.CCMR1 = tmpccmrx; 341 | 342 | //OC3M 343 | tmpccmrx = TIMx->CCMR2; 344 | tmpccmrx &= ~TIM_CCMR2_OC3M; 345 | tmpccmrx |= TIM_OCMODE_INACTIVE; 346 | htim1.CCMR2 = tmpccmrx; 347 | 348 | htim1.CCER &= ~TIM_CCER_CC1E; //CC1E =0 349 | htim1.CCER |= TIM_CCER_CC1NE; //CC1NE =1 350 | htim1.CCER |= TIM_CCER_CC2E; //CC2E =1 351 | htim1.CCER &= ~TIM_CCER_CC2NE; //CC2NE =0 352 | htim1.CCER &= ~TIM_CCER_CC3E; //CC3E =0 353 | htim1.CCER |= TIM_CCER_CC3NE; //CC3NE =1 354 | } 355 | else if(spaceVectorOut==3) 356 | { // 011 357 | //OC1M OC2M 358 | tmpccmrx = TIMx->CCMR1; 359 | tmpccmrx &= ~TIM_CCMR1_OC1M; 360 | tmpccmrx &= ~TIM_CCMR1_OC2M; 361 | tmpccmrx |= TIM_OCMODE_INACTIVE; 362 | tmpccmrx |= (TIM_OCMODE_ACTIVE << 8U); 363 | htim1.CCMR1 = tmpccmrx; 364 | 365 | //OC3M 366 | tmpccmrx = TIMx->CCMR2; 367 | tmpccmrx &= ~TIM_CCMR2_OC3M; 368 | tmpccmrx |= TIM_OCMODE_ACTIVE; 369 | htim1.CCMR2 = tmpccmrx; 370 | 371 | htim1.CCER &= ~TIM_CCER_CC1E; //CC1E =0 372 | htim1.CCER |= TIM_CCER_CC1NE; //CC1NE =1 373 | htim1.CCER |= TIM_CCER_CC2E; //CC2E =1 374 | htim1.CCER &= ~TIM_CCER_CC2NE; //CC2NE =0 375 | htim1.CCER |= TIM_CCER_CC3E; //CC3E =1 376 | htim1.CCER &= ~TIM_CCER_CC3NE; //CC3NE =0 377 | } 378 | else if(spaceVectorOut==4) 379 | { // 100 380 | //OC1M OC2M 381 | tmpccmrx = TIMx->CCMR1; 382 | tmpccmrx &= ~TIM_CCMR1_OC1M; 383 | tmpccmrx &= ~TIM_CCMR1_OC2M; 384 | tmpccmrx |= TIM_OCMODE_ACTIVE; 385 | tmpccmrx |= (TIM_OCMODE_INACTIVE << 8U); 386 | htim1.CCMR1 = tmpccmrx; 387 | 388 | //OC3M 389 | tmpccmrx = TIMx->CCMR2; 390 | tmpccmrx &= ~TIM_CCMR2_OC3M; 391 | tmpccmrx |= TIM_OCMODE_INACTIVE; 392 | htim1.CCMR2 = tmpccmrx; 393 | 394 | htim1.CCER |= TIM_CCER_CC1E; //CC1E =1 395 | htim1.CCER &= ~TIM_CCER_CC1NE; //CC1NE =0 396 | htim1.CCER &= ~TIM_CCER_CC2E; //CC2E =0 397 | htim1.CCER |= TIM_CCER_CC2NE; //CC2NE =1 398 | htim1.CCER &= ~TIM_CCER_CC3E; //CC3E =0 399 | htim1.CCER |= TIM_CCER_CC3NE; //CC3NE =1 400 | } 401 | else if(spaceVectorOut==5) 402 | { // 101 403 | //OC1M OC2M 404 | tmpccmrx = TIMx->CCMR1; 405 | tmpccmrx &= ~TIM_CCMR1_OC1M; 406 | tmpccmrx &= ~TIM_CCMR1_OC2M; 407 | tmpccmrx |= TIM_OCMODE_ACTIVE; 408 | tmpccmrx |= (TIM_OCMODE_INACTIVE << 8U); 409 | htim1.CCMR1 = tmpccmrx; 410 | 411 | //OC3M 412 | tmpccmrx = TIMx->CCMR2; 413 | tmpccmrx &= ~TIM_CCMR2_OC3M; 414 | tmpccmrx |= TIM_OCMODE_ACTIVE; 415 | htim1.CCMR2 = tmpccmrx; 416 | 417 | htim1.CCER |= TIM_CCER_CC1E; //CC1E =1 418 | htim1.CCER &= ~TIM_CCER_CC1NE; //CC1NE =0 419 | htim1.CCER &= ~TIM_CCER_CC2E; //CC2E =0 420 | htim1.CCER |= TIM_CCER_CC2NE; //CC2NE =1 421 | htim1.CCER |= TIM_CCER_CC3E; //CC3E =1 422 | htim1.CCER &= ~TIM_CCER_CC3NE; //CC3NE =0 423 | } 424 | else if(spaceVectorOut==6) 425 | { // 110 426 | //OC1M OC2M 427 | tmpccmrx = TIMx->CCMR1; 428 | tmpccmrx &= ~TIM_CCMR1_OC1M; 429 | tmpccmrx &= ~TIM_CCMR1_OC2M; 430 | tmpccmrx |= TIM_OCMODE_ACTIVE; 431 | tmpccmrx |= (TIM_OCMODE_ACTIVE << 8U); 432 | htim1.CCMR1 = tmpccmrx; 433 | 434 | //OC3M 435 | tmpccmrx = TIMx->CCMR2; 436 | tmpccmrx &= ~TIM_CCMR2_OC3M; 437 | tmpccmrx |= TIM_OCMODE_INACTIVE; 438 | htim1.CCMR2 = tmpccmrx; 439 | 440 | htim1.CCER |= TIM_CCER_CC1E; //CC1E =1 441 | htim1.CCER &= ~TIM_CCER_CC1NE; //CC1NE =0 442 | htim1.CCER |= TIM_CCER_CC2E; //CC2E =1 443 | htim1.CCER &= ~TIM_CCER_CC2NE; //CC2NE =0 444 | htim1.CCER &= ~TIM_CCER_CC3E; //CC3E =0 445 | htim1.CCER |= TIM_CCER_CC3NE; //CC3NE =1 446 | } 447 | else if(spaceVectorOut==7) 448 | { // 111 449 | //OC1M OC2M 450 | tmpccmrx = TIMx->CCMR1; 451 | tmpccmrx &= ~TIM_CCMR1_OC1M; 452 | tmpccmrx &= ~TIM_CCMR1_OC2M; 453 | tmpccmrx |= TIM_OCMODE_ACTIVE; 454 | tmpccmrx |= (TIM_OCMODE_ACTIVE << 8U); 455 | htim1.CCMR1 = tmpccmrx; 456 | 457 | //OC3M 458 | tmpccmrx = TIMx->CCMR2; 459 | tmpccmrx &= ~TIM_CCMR2_OC3M; 460 | tmpccmrx |= TIM_OCMODE_ACTIVE; 461 | htim1.CCMR2 = tmpccmrx; 462 | 463 | htim1.CCER |= TIM_CCER_CC1E; //CC1E =1 464 | htim1.CCER &= ~TIM_CCER_CC1NE; //CC1NE =0 465 | htim1.CCER |= TIM_CCER_CC2E; //CC2E =1 466 | htim1.CCER &= ~TIM_CCER_CC2NE; //CC2NE =0 467 | htim1.CCER |= TIM_CCER_CC3E; //CC3E =1 468 | htim1.CCER &= ~TIM_CCER_CC3NE; //CC3NE =0 469 | } 470 | } 471 | void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) 472 | { 473 | if(htim->Instance == TIM1) 474 | { 475 | svpwm1.b_VrefA = svpwm1.Vm * cos(6.2832*svpwm1.b_freq*svpwm1.b_TIM1PrdCnt/5000.0); 476 | svpwm1.b_VrefB = svpwm1.Vm * cos(6.2832*svpwm1.b_freq*svpwm1.b_TIM1PrdCnt/5000.0 - 6.2832/3.0); 477 | svpwm1.b_VrefC = svpwm1.Vm * cos(6.2832*svpwm1.b_freq*svpwm1.b_TIM1PrdCnt/5000.0 + 6.2832/3.0); 478 | 479 | // 0 <= Vm <=1 480 | // to avoid over modulation, scale down the Vref 481 | svpwm1.b_VrefA *= 0.8660; 482 | svpwm1.b_VrefB *= 0.8660; 483 | svpwm1.b_VrefC *= 0.8660; 484 | 485 | Clark_Transformation(&svpwm1.b_VrefA, &svpwm1.b_VrefB, &svpwm1.b_VrefC, &svpwm1.b_VrefAlpha, &svpwm1.b_VrefBeta); 486 | sectorJudge(&svpwm1); 487 | SpaceVectorUpdate(&svpwm1); 488 | 489 | TIM1CmprLoad(); 490 | 491 | SVPWM1_SpaceVectorDRV(svpwm1.a_VectorOut[2]); 492 | 493 | svpwm1.b_TIM1PrdCnt++; 494 | if(svpwm1.b_TIM1PrdCnt==100) 495 | { 496 | svpwm1.b_TIM1PrdCnt = 0; 497 | } 498 | } 499 | } 500 | 501 | void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim) 502 | { 503 | if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) 504 | { 505 | SVPWM1_SpaceVectorDRV(svpwm1.a_VectorOut[0]); 506 | } 507 | if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2) 508 | { 509 | SVPWM1_SpaceVectorDRV(svpwm1.a_VectorOut[1]); 510 | } 511 | if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_3) 512 | { 513 | SVPWM1_SpaceVectorDRV(svpwm1.a_VectorOut[0]); 514 | } 515 | if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_4) 516 | { 517 | SVPWM1_SpaceVectorDRV(svpwm1.a_VectorOut[2]); 518 | } 519 | 520 | } 521 | -------------------------------------------------------------------------------- /svpwm.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef __SVPWM_H__ 4 | #define __SVPWM_H__ 5 | 6 | #include "main.h" 7 | #include "stm32f1xx_hal.h" 8 | 9 | 10 | 11 | #define PI 3.1416 12 | 13 | extern TIM_HandleTypeDef htim1; 14 | 15 | typedef struct 16 | { 17 | uint32_t b_TIM1PrdCnt; 18 | // b_VrefA = b_Vm * cos(2*pi*b_freq*t) 19 | // b_VrefB = b_Vm * cos(2*pi*b_freq*t - 2*pi/3) 20 | // b_VrefC = b_Vm * cos(2*pi*b_freq*t + 2*pi/3) 21 | float b_VrefA, b_VrefB, b_VrefC; 22 | float b_Vm, b_freq; 23 | float b_VrefAlpha, b_VrefBeta; 24 | 25 | uint8_t b_sector; 26 | float b_VrefAngle; 27 | 28 | //space vector 29 | //0 : 000 1: 001 2: 010 3: 011 4: 100 5: 101 6: 110 7: 111 30 | uint8_t a_VectorOut[3]; 31 | float a_VectorOutDuty[3]; 32 | uint32_t a_VectorOutDutyCmpr[4]; 33 | 34 | } BLDC_SVPWMTypeDef; 35 | 36 | 37 | extern BLDC_SVPWMTypeDef svpwm1; 38 | 39 | 40 | 41 | 42 | void Clark_Transformation(float* In_a, float* In_b, float* In_c, float* Out_alpha, float* Out_beta); 43 | void InvClark_Transformation(float* In_alpha, float* In_beta, float* Out_a, float* Out_b, float* Out_c); 44 | void sectorJudge(BLDC_SVPWMTypeDef* svpwm); 45 | void SpaceVectorUpdate(BLDC_SVPWMTypeDef* svpwm); 46 | void TIM1CmprLoad(void); 47 | void SVPWM1_SpaceVectorDRV(uint8_t spaceVectorOut); 48 | void SVPWM1_SpaceVectorDRV_v2(uint8_t spaceVectorOut); 49 | void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim); 50 | void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim); 51 | 52 | 53 | 54 | 55 | #endif 56 | 57 | --------------------------------------------------------------------------------