servodisc goodness

Dependencies:   mbed-dev-f303

Committer:
benkatz
Date:
Wed Dec 13 05:04:38 2017 +0000
Revision:
3:2e9713c61c2d
Parent:
1:27b535673eed
Child:
4:6e290eb553cd
controller parameters seem good

Who changed what in which revision?

UserRevisionLine numberNew contents of line
benkatz 0:92d18e011d98 1 #include "mbed.h"
benkatz 0:92d18e011d98 2
benkatz 1:27b535673eed 3 #define PI 3.14159265f
benkatz 1:27b535673eed 4 #define PWM_ARR 0x2E8 // PWM timer auto-reload
benkatz 1:27b535673eed 5 #define DT 0.00002067f // PWM_ARR/36 MHz
benkatz 1:27b535673eed 6 #define CPR 8000.0f // Encoder counts/revolution
benkatz 3:2e9713c61c2d 7 #define J 0.000065f // Inertia
benkatz 3:2e9713c61c2d 8 #define KT 0.0678f // Torque Constant
benkatz 1:27b535673eed 9 #define R 0.85f // Resistance
benkatz 3:2e9713c61c2d 10 #define V_IN 20.0f // DC input voltage
benkatz 3:2e9713c61c2d 11 #define K_SAT 22000.0f // Controller saturation gain
benkatz 3:2e9713c61c2d 12 #define DTC_MAX 0.97f // Max duty cycle (limited by bootstrapping)
benkatz 1:27b535673eed 13 #define V V_IN*DTC_MAX // Max useable voltage
benkatz 0:92d18e011d98 14
benkatz 3:2e9713c61c2d 15 #define TICKSTORAD(x) (float)x*2.0f*PI/CPR
benkatz 0:92d18e011d98 16 #define CONSTRAIN(x,min,max) ((x)<(min)?(min):((x)>(max)?(max):(x)))
benkatz 0:92d18e011d98 17
benkatz 1:27b535673eed 18 Serial pc (PA_2, PA_3); // Serial to programming header
benkatz 1:27b535673eed 19 Serial io(PB_6, PB_7); // Differential Serial to JST Header
benkatz 1:27b535673eed 20 DigitalIn id_1(PB_3); // ID Setting Jumpers
benkatz 1:27b535673eed 21 DigitalIn id_2(PB_4);
benkatz 1:27b535673eed 22 DigitalIn id_3(PB_5);
benkatz 1:27b535673eed 23 DigitalOut led(PA_15); // Debug LED
benkatz 1:27b535673eed 24 DigitalIn d_in(PA_4); // LED on input from AND Board
benkatz 1:27b535673eed 25 DigitalOut d_out(PA_5); // LED on output to AND Board
benkatz 0:92d18e011d98 26
benkatz 0:92d18e011d98 27
benkatz 0:92d18e011d98 28 void Control();
benkatz 0:92d18e011d98 29 void InitEncoder();
benkatz 0:92d18e011d98 30 void InitPWM();
benkatz 1:27b535673eed 31 void InitGPIO();
benkatz 0:92d18e011d98 32 void WriteVoltage( float v);
benkatz 1:27b535673eed 33 int GetID();
benkatz 3:2e9713c61c2d 34 void SerialISR(void);
benkatz 0:92d18e011d98 35
benkatz 0:92d18e011d98 36
benkatz 0:92d18e011d98 37
benkatz 0:92d18e011d98 38 /* Control Variables */
benkatz 1:27b535673eed 39 int id;
benkatz 3:2e9713c61c2d 40 int q_raw, dir, dq_raw = 0;
benkatz 3:2e9713c61c2d 41 float q, q_old, dq, u, e, q_ref, dqdebug = 0;
benkatz 3:2e9713c61c2d 42 int count, count2;
benkatz 3:2e9713c61c2d 43 int controlmode =0;
benkatz 3:2e9713c61c2d 44
benkatz 3:2e9713c61c2d 45 /* Kalman Filter Variables */
benkatz 3:2e9713c61c2d 46 float q_est[2] = {0.0f};
benkatz 3:2e9713c61c2d 47 float q_meas[2] = {0.0f};
benkatz 3:2e9713c61c2d 48 float F[2][2] = {{1.0f, DT},{0.0f, 1.0f}};
benkatz 3:2e9713c61c2d 49 float B[2] = {0.0f, DT/J};
benkatz 3:2e9713c61c2d 50 float P[2][2] = {0};
benkatz 3:2e9713c61c2d 51 float Q[2] = {1.0f, 0.01f};
benkatz 3:2e9713c61c2d 52 float Rk[2] = {0.01, 10};
benkatz 3:2e9713c61c2d 53 float S[2][2] = {0};
benkatz 3:2e9713c61c2d 54 float Y[2] = {0};
benkatz 3:2e9713c61c2d 55 float K[2][2] = {0};
benkatz 3:2e9713c61c2d 56 float U;
benkatz 3:2e9713c61c2d 57
benkatz 3:2e9713c61c2d 58
benkatz 3:2e9713c61c2d 59 int16_t log_vec[2500] = {0};
benkatz 3:2e9713c61c2d 60 //int16_t log_vec_2[1250] = {0};
benkatz 3:2e9713c61c2d 61
benkatz 0:92d18e011d98 62
benkatz 1:27b535673eed 63 /* PWM Timer Interrupt */
benkatz 1:27b535673eed 64 extern "C" void TIM1_UP_TIM16_IRQHandler(void) {
benkatz 0:92d18e011d98 65 if (TIM1->SR & TIM_SR_UIF ) {
benkatz 0:92d18e011d98 66 }
benkatz 0:92d18e011d98 67 count++;
benkatz 3:2e9713c61c2d 68
benkatz 3:2e9713c61c2d 69 if(count>1000 && count<2000){
benkatz 3:2e9713c61c2d 70 q_ref = 1.57f;
benkatz 3:2e9713c61c2d 71 //ref = 18000.0f;
benkatz 3:2e9713c61c2d 72 }
benkatz 3:2e9713c61c2d 73
benkatz 3:2e9713c61c2d 74 if(count>2000 && count<3000){
benkatz 3:2e9713c61c2d 75 q_ref = 0.0f;
benkatz 3:2e9713c61c2d 76 //ref = 0;
benkatz 3:2e9713c61c2d 77 //count = 0;
benkatz 3:2e9713c61c2d 78 }
benkatz 3:2e9713c61c2d 79 if(count>3000 && count<4000){
benkatz 3:2e9713c61c2d 80 q_ref = -1.57f;
benkatz 3:2e9713c61c2d 81 }
benkatz 3:2e9713c61c2d 82
benkatz 3:2e9713c61c2d 83 if(count>4500){
benkatz 3:2e9713c61c2d 84 controlmode = 1;
benkatz 3:2e9713c61c2d 85 }
benkatz 3:2e9713c61c2d 86 if(count<5000){
benkatz 3:2e9713c61c2d 87 //log_vec_2[count/4] = (int)(q_est[1]*10.0f);
benkatz 3:2e9713c61c2d 88 log_vec[count/2] = (int)(q*1000.0f);
benkatz 3:2e9713c61c2d 89 }
benkatz 3:2e9713c61c2d 90
benkatz 3:2e9713c61c2d 91 if(count>20000 && count<22500){
benkatz 3:2e9713c61c2d 92 //printf("%d\n\r", log_vec[count2]);
benkatz 3:2e9713c61c2d 93 //wait_us(200);
benkatz 3:2e9713c61c2d 94 //printf("%d\n\r", log_vec_2[count2]);
benkatz 3:2e9713c61c2d 95 //wait_us(200);
benkatz 3:2e9713c61c2d 96 count2++;
benkatz 3:2e9713c61c2d 97 }
benkatz 3:2e9713c61c2d 98
benkatz 3:2e9713c61c2d 99
benkatz 0:92d18e011d98 100 Control();
benkatz 3:2e9713c61c2d 101 /*
benkatz 1:27b535673eed 102 if(count > 5000){
benkatz 3:2e9713c61c2d 103 //io.printf("derp\n\r");
benkatz 3:2e9713c61c2d 104 //pc.printf("derp\n\r");
benkatz 3:2e9713c61c2d 105 //pc.printf("%d %f\n\r", q_raw, e);
benkatz 3:2e9713c61c2d 106 printf("%f %f\n\r", dq, dqdebug);
benkatz 3:2e9713c61c2d 107 //d_out = !d_out;
benkatz 0:92d18e011d98 108 count = 0;
benkatz 0:92d18e011d98 109 }
benkatz 3:2e9713c61c2d 110 */
benkatz 0:92d18e011d98 111 TIM1->SR = 0x0; // reset the status register
benkatz 0:92d18e011d98 112 }
benkatz 0:92d18e011d98 113
benkatz 3:2e9713c61c2d 114
benkatz 0:92d18e011d98 115 /* Main Loop */
benkatz 0:92d18e011d98 116 int main() {
benkatz 1:27b535673eed 117
benkatz 3:2e9713c61c2d 118 pc.baud(921600);
benkatz 1:27b535673eed 119 io.baud(921600);
benkatz 3:2e9713c61c2d 120
benkatz 3:2e9713c61c2d 121 //pc.printf("\n\r Rubix Controller\n\r");
benkatz 1:27b535673eed 122 id_1.mode(PullUp);
benkatz 1:27b535673eed 123 id_2.mode(PullUp);
benkatz 1:27b535673eed 124 id_3.mode(PullUp);
benkatz 3:2e9713c61c2d 125 id = GetID();
benkatz 3:2e9713c61c2d 126 pc.printf(" Motor ID: %d\n\r", id);
benkatz 3:2e9713c61c2d 127
benkatz 3:2e9713c61c2d 128 //d_in.mode(PullDown);
benkatz 1:27b535673eed 129 led = 1;
benkatz 1:27b535673eed 130 d_out = 1;
benkatz 3:2e9713c61c2d 131 //wait(.1);
benkatz 1:27b535673eed 132
benkatz 0:92d18e011d98 133 InitPWM();
benkatz 3:2e9713c61c2d 134 InitEncoder();
benkatz 3:2e9713c61c2d 135 //pc.printf("Initializing Encoder\n\r");
benkatz 3:2e9713c61c2d 136 //pc.printf("Initializing PWM\n\r");
benkatz 3:2e9713c61c2d 137 //wait(.1);
benkatz 0:92d18e011d98 138 while(1) {
benkatz 0:92d18e011d98 139 }
benkatz 0:92d18e011d98 140 }
benkatz 0:92d18e011d98 141
benkatz 1:27b535673eed 142 /* Position Control */
benkatz 0:92d18e011d98 143 void Control(void){
benkatz 3:2e9713c61c2d 144
benkatz 3:2e9713c61c2d 145 // Sample Position and Velocity //
benkatz 3:2e9713c61c2d 146 q_raw = TIM2->CNT;
benkatz 3:2e9713c61c2d 147 dir = -2*(((TIM2->CR1)>>4)&1)+1;
benkatz 3:2e9713c61c2d 148 dq_raw = dir*(TIM15->CCR1);
benkatz 0:92d18e011d98 149 q = TICKSTORAD(q_raw);
benkatz 3:2e9713c61c2d 150 //dq = (q - q_old)/DT;
benkatz 3:2e9713c61c2d 151 dq = (18000000.0f*4.0f*2.0f*PI/CPR)/((float)dq_raw);
benkatz 3:2e9713c61c2d 152 if(isinf(dq)){ dq = 0.0f;}
benkatz 0:92d18e011d98 153 q_old = q;
benkatz 3:2e9713c61c2d 154
benkatz 3:2e9713c61c2d 155 q_meas[0] = q;
benkatz 3:2e9713c61c2d 156 q_meas[1] = dq;
benkatz 3:2e9713c61c2d 157
benkatz 3:2e9713c61c2d 158 // Kalman Filter //
benkatz 3:2e9713c61c2d 159 // Update Model //
benkatz 3:2e9713c61c2d 160
benkatz 3:2e9713c61c2d 161 q_est[0] += q_est[1]*F[0][1];
benkatz 3:2e9713c61c2d 162 q_est[1] += B[1]*U;
benkatz 3:2e9713c61c2d 163
benkatz 3:2e9713c61c2d 164
benkatz 3:2e9713c61c2d 165 P[0][0] += Q[0] + DT*P[1][0] + DT*(P[0][1] + DT*P[1][1]);
benkatz 3:2e9713c61c2d 166 P[0][1] += DT*P[1][1];
benkatz 3:2e9713c61c2d 167 P[1][0] += DT*P[1][1];
benkatz 3:2e9713c61c2d 168 P[1][1] += Q[1];
benkatz 3:2e9713c61c2d 169
benkatz 3:2e9713c61c2d 170 //Calculate Kalman Gains//
benkatz 3:2e9713c61c2d 171 S[0][0] = P[0][0] + Rk[0];
benkatz 3:2e9713c61c2d 172 S[0][1] = P[0][1];
benkatz 3:2e9713c61c2d 173 S[1][0] = P[1][0];
benkatz 3:2e9713c61c2d 174 S[1][1] = P[1][1] + Rk[1];
benkatz 3:2e9713c61c2d 175 float denom = (S[0][0]*S[1][1] - S[0][1]*S[1][0]);
benkatz 3:2e9713c61c2d 176 K[0][0] = (P[0][0]*S[1][1])/denom - (P[0][1]*S[1][0])/denom;
benkatz 3:2e9713c61c2d 177 K[0][1] = (P[0][1]*S[0][0])/denom - (P[0][0]*S[0][1])/denom;
benkatz 3:2e9713c61c2d 178 K[1][0] = (P[1][0]*S[1][1])/(S[0][0]*S[1][1] - S[0][1]*S[1][0]) - (P[1][1]*S[1][0])/denom;
benkatz 3:2e9713c61c2d 179 K[1][1] = (P[1][1]*S[0][0])/(S[0][0]*S[1][1] - S[0][1]*S[1][0]) - (P[1][0]*S[0][1])/denom;
benkatz 3:2e9713c61c2d 180
benkatz 3:2e9713c61c2d 181 Y[0] = q_meas[0] - q_est[0];
benkatz 3:2e9713c61c2d 182 Y[1] = q_meas[1] - q_est[1];
benkatz 3:2e9713c61c2d 183
benkatz 3:2e9713c61c2d 184 // Update Estimate //
benkatz 3:2e9713c61c2d 185 q_est[0] += K[0][0]*Y[0] + K[0][1]*Y[1];
benkatz 3:2e9713c61c2d 186 q_est[1] += K[1][0]*Y[0] + K[1][1]*Y[1];
benkatz 3:2e9713c61c2d 187
benkatz 3:2e9713c61c2d 188 P[0][0] = -K[0][1]*P[1][0] - P[0][0]*(K[0][0] - 1.0f);
benkatz 3:2e9713c61c2d 189 P[0][1] = -K[0][1]*P[1][1] - P[0][1]*(K[0][0] - 1.0f);
benkatz 3:2e9713c61c2d 190 P[1][0] = -K[1][0]*P[0][0] - P[1][0]*(K[1][1] - 1.0f);
benkatz 3:2e9713c61c2d 191 P[1][1] = -K[1][0]*P[0][1] - P[1][1]*(K[1][1] - 1.0f);
benkatz 3:2e9713c61c2d 192
benkatz 3:2e9713c61c2d 193
benkatz 3:2e9713c61c2d 194
benkatz 3:2e9713c61c2d 195 // Control Law //
benkatz 3:2e9713c61c2d 196 if(controlmode == 0){
benkatz 3:2e9713c61c2d 197 e = K_SAT*((q_ref - q) + (abs(dq)*dq*1.3f*R*J)/(2.0f*KT*(-V - KT*abs(dq)))); // Bullshit sliding mode control with nonlinear sliding surface, for minimum-time response
benkatz 3:2e9713c61c2d 198 //e = K_SAT*((q_ref - q) + (abs(q_est[1])*q_est[1]*1.3f*R*J)/(2.0f*KT*(-V - 1.0f*KT*abs(q_est[1])))); // Bullshit sliding mode control with nonlinear sliding surface, for minimum-time response
benkatz 3:2e9713c61c2d 199
benkatz 3:2e9713c61c2d 200 }
benkatz 3:2e9713c61c2d 201 //q_ref = 0.0f;
benkatz 3:2e9713c61c2d 202 if(controlmode == 1){
benkatz 3:2e9713c61c2d 203 e = 0;
benkatz 3:2e9713c61c2d 204 //e = 40.0f*(q_ref - q) + .2f*(0.0f-dq);
benkatz 3:2e9713c61c2d 205 }
benkatz 0:92d18e011d98 206 u = CONSTRAIN(e, -V, V);
benkatz 3:2e9713c61c2d 207 WriteVoltage(u);
benkatz 3:2e9713c61c2d 208 U = KT*(u - KT*dq)/R;
benkatz 3:2e9713c61c2d 209 //WriteVoltage(-10.0f);
benkatz 1:27b535673eed 210 }
benkatz 1:27b535673eed 211
benkatz 1:27b535673eed 212 /* Set motor voltage */
benkatz 1:27b535673eed 213 void WriteVoltage(float v){
benkatz 1:27b535673eed 214 if(v>0){
benkatz 1:27b535673eed 215 TIM1->CCR1 = 0;
benkatz 1:27b535673eed 216 TIM1->CCR2 = (int) (PWM_ARR*(v/V));
benkatz 1:27b535673eed 217 }
benkatz 3:2e9713c61c2d 218 else if(v<=0){
benkatz 1:27b535673eed 219 TIM1->CCR2 = 0;
benkatz 3:2e9713c61c2d 220 TIM1->CCR1 = (int) (PWM_ARR*(abs(v)/V));
benkatz 1:27b535673eed 221 }
benkatz 0:92d18e011d98 222 }
benkatz 0:92d18e011d98 223
benkatz 3:2e9713c61c2d 224 void SerialISR(void){
benkatz 3:2e9713c61c2d 225 // PC Serial Interrupt //
benkatz 3:2e9713c61c2d 226
benkatz 3:2e9713c61c2d 227
benkatz 3:2e9713c61c2d 228 }
benkatz 3:2e9713c61c2d 229
benkatz 3:2e9713c61c2d 230
benkatz 1:27b535673eed 231 /* Read ID Jumpers */
benkatz 1:27b535673eed 232 int GetID(void){
benkatz 1:27b535673eed 233 int i1 = !id_1.read();
benkatz 1:27b535673eed 234 int i2 = !id_2.read();
benkatz 1:27b535673eed 235 int i3 = !id_3.read();
benkatz 1:27b535673eed 236 return (i1<<2) | (i2<<1) | i3;
benkatz 0:92d18e011d98 237 }
benkatz 0:92d18e011d98 238
benkatz 1:27b535673eed 239 /* Initialize Encoder */
benkatz 0:92d18e011d98 240 void InitEncoder(void) {
benkatz 0:92d18e011d98 241 // configure GPIO PA0 & PA1 as inputs for Encoder
benkatz 3:2e9713c61c2d 242 //RCC->AHBENR |= RCC_AHBENR_GPIOAEN; // enable the clock to GPIOA
benkatz 1:27b535673eed 243 GPIOA->MODER |= GPIO_MODER_MODER0_1 | GPIO_MODER_MODER1_1 ; // PA0 & PA1 as Alternate Function
benkatz 1:27b535673eed 244 GPIOA->OTYPER |= GPIO_OTYPER_OT_0 | GPIO_OTYPER_OT_1 ; // PA0 & PA1 as Inputs
benkatz 1:27b535673eed 245 GPIOA->OSPEEDR |= 0x00000011; // GPIO Speed
benkatz 3:2e9713c61c2d 246 //GPIOA->PUPDR |= GPIO_PUPDR_PUPDR0_1 | GPIO_PUPDR_PUPDR1_1 ; // Pull Down
benkatz 1:27b535673eed 247 GPIOA->AFR[0] |= 0x00000011 ; // AF01 for PA0 & PA1
benkatz 1:27b535673eed 248 GPIOA->AFR[1] |= 0x00000000 ; //
benkatz 1:27b535673eed 249
benkatz 0:92d18e011d98 250 // configure TIM2 as Encoder input
benkatz 3:2e9713c61c2d 251 TIM2->DIER = 0x00;
benkatz 3:2e9713c61c2d 252 TIM2->EGR = 0x0;
benkatz 3:2e9713c61c2d 253 NVIC_DisableIRQ(TIM2_IRQn);
benkatz 3:2e9713c61c2d 254
benkatz 1:27b535673eed 255 RCC->APB1ENR |= 0x00000001; // Enable clock for TIM2
benkatz 1:27b535673eed 256 TIM2->CR1 = 0x0001; // CEN(Counter Enable)='1'
benkatz 1:27b535673eed 257 TIM2->SMCR = 0x0003; // SMS='011' (Encoder mode 3)
benkatz 1:27b535673eed 258 TIM2->CCMR1 = 0x5151; // CC1S='01' CC2S='01'
benkatz 1:27b535673eed 259 TIM2->CCMR2 = 0x0000;
benkatz 1:27b535673eed 260 TIM2->CCER = 0x0011; // CC1P CC2P
benkatz 1:27b535673eed 261 TIM2->PSC = 0x0000; // Prescaler = (0+1)
benkatz 1:27b535673eed 262 TIM2->CNT = 0x0000; //reset the counter before we use it
benkatz 3:2e9713c61c2d 263
benkatz 3:2e9713c61c2d 264 TIM2->CR2 = 0x030; //MMS = 101
benkatz 3:2e9713c61c2d 265 __TIM15_CLK_ENABLE();
benkatz 3:2e9713c61c2d 266 TIM15->PSC = 0x03;
benkatz 3:2e9713c61c2d 267 TIM15->SMCR = 0x4; //TS = 010 for ITR2, SMS = 100
benkatz 3:2e9713c61c2d 268 TIM15->CCMR1 = 0x3;// CC1S = 11, IC1 mapped on TRC
benkatz 3:2e9713c61c2d 269 TIM15->CCER |= TIM_CCER_CC1P;
benkatz 3:2e9713c61c2d 270 TIM15->CCER |= TIM_CCER_CC1E;
benkatz 3:2e9713c61c2d 271 TIM15->CR1 = 0x1;
benkatz 3:2e9713c61c2d 272
benkatz 0:92d18e011d98 273 }
benkatz 0:92d18e011d98 274
benkatz 3:2e9713c61c2d 275
benkatz 1:27b535673eed 276 /* Initialize PWM */
benkatz 0:92d18e011d98 277 void InitPWM(void){
benkatz 1:27b535673eed 278 RCC->AHBENR |= RCC_AHBENR_GPIOAEN; // enable the clock to GPIOA
benkatz 1:27b535673eed 279 RCC->AHBENR |= RCC_AHBENR_GPIOBEN; // enable the clock to GPIOB
benkatz 1:27b535673eed 280 RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; // enable TIM1 clock
benkatz 0:92d18e011d98 281
benkatz 0:92d18e011d98 282 GPIOA->MODER |= GPIO_MODER_MODER7_1 | GPIO_MODER_MODER8_1 | GPIO_MODER_MODER9_1 ; //PA_7, PA_8, PA_9 to alternate funtion mode
benkatz 0:92d18e011d98 283 GPIOB->MODER |= GPIO_MODER_MODER0_1; // PB_0 to alternate function mode
benkatz 0:92d18e011d98 284 GPIOA->AFR[0] |= 0x60000000; // PA_7 to alternate function 6
benkatz 0:92d18e011d98 285 GPIOA->AFR[1] |= 0x00000066; // PA_8, PA_9 to alternate function 6
benkatz 0:92d18e011d98 286 GPIOB->AFR[0] |= 0x00000006; // PB_0 to alternate function 6
benkatz 0:92d18e011d98 287
benkatz 0:92d18e011d98 288 //PWM Setup
benkatz 0:92d18e011d98 289 TIM1->CCMR1 |= 0x6060; // Enable output compare 1 and 2
benkatz 0:92d18e011d98 290 TIM1->CCER |= TIM_CCER_CC1E | TIM_CCER_CC1NE | TIM_CCER_CC2NE | TIM_CCER_CC2E; // enable outputs 1, 2, and complementary outputs
benkatz 1:27b535673eed 291 TIM1->BDTR |= TIM_BDTR_MOE | 0xF; // MOE = 1 | set dead-time
benkatz 1:27b535673eed 292 TIM1->PSC = 0x0; // no prescaler, timer counts up in sync with the peripheral clock
benkatz 1:27b535673eed 293 TIM1->ARR = PWM_ARR; // set auto reload
benkatz 1:27b535673eed 294 TIM1->CR1 |= TIM_CR1_ARPE; // autoreload on,
benkatz 1:27b535673eed 295 TIM1->CR1 |= TIM_CR1_CEN; // enable TIM1
benkatz 0:92d18e011d98 296
benkatz 3:2e9713c61c2d 297
benkatz 1:27b535673eed 298 NVIC_EnableIRQ(TIM1_UP_TIM16_IRQn); //Enable TIM1 IRQ
benkatz 1:27b535673eed 299 TIM1->DIER |= TIM_DIER_UIE; // enable update interrupt
benkatz 1:27b535673eed 300 TIM1->CR1 |= 0x40; //CMS = 10, interrupt only when counting up
benkatz 1:27b535673eed 301 TIM1->RCR |= 0x001; // update event once per up/down count of tim1
benkatz 3:2e9713c61c2d 302 TIM1->EGR |= TIM_EGR_UG;
benkatz 3:2e9713c61c2d 303
benkatz 3:2e9713c61c2d 304 }
benkatz 3:2e9713c61c2d 305