Test application for getting the Nucleo F0 30 board to work with Evan's prototype LED board.

Dependencies:   mbed

Committer:
bgrissom
Date:
Fri Aug 08 16:58:46 2014 +0000
Revision:
6:e4da8955cf65
Parent:
5:9a662dec2ddb
Support for a faster PWM on the STM32 F072 chip (was running much slower previously).

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bgrissom 1:256d7a2f8391 1 #include "mbed.h"
bgrissom 2:a57a5501152c 2
bgrissom 2:a57a5501152c 3 #define OK (0)
bgrissom 2:a57a5501152c 4 #define ERROR (-1)
bgrissom 2:a57a5501152c 5
bgrissom 5:9a662dec2ddb 6 #define PIN_41 PB_5
bgrissom 5:9a662dec2ddb 7 #define PIN_46 PB_9
bgrissom 5:9a662dec2ddb 8 #define PIN_32 PA_11
bgrissom 5:9a662dec2ddb 9 #define PIN_20 PB_2
bgrissom 5:9a662dec2ddb 10 #define HEX_ONE_THOUSAND (0x03E8)
bgrissom 5:9a662dec2ddb 11
bgrissom 5:9a662dec2ddb 12 DigitalOut ENA(PIN_41);
bgrissom 5:9a662dec2ddb 13 DigitalOut ENB(PIN_46);
bgrissom 5:9a662dec2ddb 14 DigitalOut ENC(PIN_32);
bgrissom 5:9a662dec2ddb 15 DigitalOut EnSclk(PIN_20);
bgrissom 5:9a662dec2ddb 16
bgrissom 5:9a662dec2ddb 17
bgrissom 2:a57a5501152c 18 // Forward Declarations
bgrissom 2:a57a5501152c 19 void pwmout_period_ns(pwmout_t* obj, int us);
bgrissom 2:a57a5501152c 20 int cmd_S0(uint16_t value);
bgrissom 2:a57a5501152c 21 void cmd_S1(void);
bgrissom 2:a57a5501152c 22
bgrissom 3:6f12c437ab88 23 // Globals
bgrissom 2:a57a5501152c 24 bool gSpiMode = false;
bgrissom 2:a57a5501152c 25 SPI* gSpiPtr = NULL;
bgrissom 5:9a662dec2ddb 26 DigitalOut gbbTRANS(PA_4); // Global bit bang TRANS (data) line
bgrissom 5:9a662dec2ddb 27 const int SCLK_ENABLED = 0;
bgrissom 3:6f12c437ab88 28
bgrissom 2:a57a5501152c 29
bgrissom 1:256d7a2f8391 30 int main() {
bgrissom 5:9a662dec2ddb 31 ENA = 1;
bgrissom 5:9a662dec2ddb 32 ENB = 1;
bgrissom 5:9a662dec2ddb 33 ENC = 1;
bgrissom 5:9a662dec2ddb 34 EnSclk = SCLK_ENABLED;
bgrissom 5:9a662dec2ddb 35
bgrissom 5:9a662dec2ddb 36
bgrissom 1:256d7a2f8391 37 // NOTE: 24MHz is half the 48MHz clock rate. The PWM registers
bgrissom 1:256d7a2f8391 38 // seem to only allow 24MHz at this point, so I'm matching
bgrissom 1:256d7a2f8391 39 // the SPI bus speed to be the same.
bgrissom 1:256d7a2f8391 40 //
bgrissom 1:256d7a2f8391 41 // 1/24MHz => 1/(24*10^6) => 41.6*10^-9 second period,
bgrissom 1:256d7a2f8391 42 // which means 41.6ns period and 20.8ns pulse width at
bgrissom 1:256d7a2f8391 43 // 50% duty cycle (which seems to be right for the SPI clock
bgrissom 1:256d7a2f8391 44 // line as well as a reasonable choice for the PWM line).
bgrissom 0:b0f98b83cb07 45
bgrissom 3:6f12c437ab88 46 // BAG ORIG: gbbTRANS = 1; // Start with TRANS high. It acts like a SPI slave select
bgrissom 3:6f12c437ab88 47 // that is active-low.
bgrissom 3:6f12c437ab88 48 gbbTRANS = 0;
bgrissom 0:b0f98b83cb07 49
bgrissom 3:6f12c437ab88 50 // PWMCLK
bgrissom 2:a57a5501152c 51 pwmout_t outs;
bgrissom 5:9a662dec2ddb 52 pwmout_init(&outs, PB_4);
bgrissom 6:e4da8955cf65 53 pwmout_period_ns(&outs, 2); // 24 MHz (not very clean on the scope)
bgrissom 4:4eeacb39a417 54 // pwmout_period_ns(&outs, 40); // 1.2 MHz on the scope
bgrissom 6:e4da8955cf65 55 // Very slow! pwmout_period_us(&outs, 2);
bgrissom 2:a57a5501152c 56 pwmout_write(&outs, 0.5f);
bgrissom 2:a57a5501152c 57
bgrissom 2:a57a5501152c 58 int ret = OK; // Return value
bgrissom 2:a57a5501152c 59 int i = 0;
bgrissom 2:a57a5501152c 60
bgrissom 4:4eeacb39a417 61 printf("17:10\n");
bgrissom 2:a57a5501152c 62
bgrissom 5:9a662dec2ddb 63 //while (1) {
bgrissom 5:9a662dec2ddb 64 for (i=0; i<400; i++) {
bgrissom 5:9a662dec2ddb 65 ret = cmd_S0(0x0900);
bgrissom 3:6f12c437ab88 66 // ORIG: ret = cmd_S0(0xFFFF);
bgrissom 2:a57a5501152c 67 if (ret != OK) {
bgrissom 2:a57a5501152c 68 printf("ERROR cmd_S0()\n");
bgrissom 2:a57a5501152c 69 return ERROR;
bgrissom 2:a57a5501152c 70 }
bgrissom 2:a57a5501152c 71 }
bgrissom 2:a57a5501152c 72 cmd_S1();
bgrissom 5:9a662dec2ddb 73 //}
bgrissom 2:a57a5501152c 74 }
bgrissom 0:b0f98b83cb07 75
bgrissom 2:a57a5501152c 76
bgrissom 0:b0f98b83cb07 77
bgrissom 2:a57a5501152c 78 // S0 Command:
bgrissom 2:a57a5501152c 79 // Needs only SCK and SIN (which are SPI_SCK and SPI_MOSI respectively).
bgrissom 2:a57a5501152c 80 // This is because TRANS can be 0 for this command according to the datasheet.
bgrissom 2:a57a5501152c 81 int cmd_S0(uint16_t value) {
bgrissom 2:a57a5501152c 82 // Command S0 and S1 share the same clock line, so we need to be
bgrissom 2:a57a5501152c 83 // careful which mode we are in. This avoids re-initializing these
bgrissom 2:a57a5501152c 84 // pins if we are already in SPI mode.
bgrissom 2:a57a5501152c 85 // WARNING: Re-initializing every time makes the MOSI line dirty and
bgrissom 2:a57a5501152c 86 // is wasteful for the CPU.
bgrissom 2:a57a5501152c 87 if ( gSpiMode == false &&
bgrissom 2:a57a5501152c 88 gSpiPtr == NULL)
bgrissom 2:a57a5501152c 89 {
bgrissom 2:a57a5501152c 90 // We are not using MISO, this is a one-way bus
bgrissom 2:a57a5501152c 91 gSpiPtr = new SPI(SPI_MOSI, NC, SPI_SCK);
bgrissom 1:256d7a2f8391 92
bgrissom 2:a57a5501152c 93 if (gSpiPtr == NULL) {
bgrissom 2:a57a5501152c 94 printf("ERROR: Could not allocate SPI\n");
bgrissom 2:a57a5501152c 95 return ERROR;
bgrissom 2:a57a5501152c 96 }
bgrissom 1:256d7a2f8391 97
bgrissom 2:a57a5501152c 98 // Note: Polarity and phase are both 0 for the TC62D723FNG
bgrissom 2:a57a5501152c 99 // For a graphical reminder on polarity and phase, visit:
bgrissom 2:a57a5501152c 100 // http://www.eetimes.com/document.asp?doc_id=1272534
bgrissom 2:a57a5501152c 101 gSpiPtr->format(16, 0);
bgrissom 4:4eeacb39a417 102 // gSpiPtr->frequency(1000000); // 1.5 MHz on the scope
bgrissom 3:6f12c437ab88 103 gSpiPtr->frequency(24000000); // 24 MHz
bgrissom 2:a57a5501152c 104 gSpiMode = true;
bgrissom 2:a57a5501152c 105 }
bgrissom 3:6f12c437ab88 106 gbbTRANS = 0; // Like an SPI slave select
bgrissom 2:a57a5501152c 107 gSpiPtr->write(value);
bgrissom 3:6f12c437ab88 108 gbbTRANS = 1; // Like an SPI slave select
bgrissom 4:4eeacb39a417 109 // LONGTERM OPTIMIZATION: Evan suggests setting it
bgrissom 4:4eeacb39a417 110 // wait_us(1);
bgrissom 4:4eeacb39a417 111 // gbbTRANS = 0; // Set back low
bgrissom 2:a57a5501152c 112 return OK;
bgrissom 2:a57a5501152c 113 }
bgrissom 1:256d7a2f8391 114
bgrissom 0:b0f98b83cb07 115
bgrissom 0:b0f98b83cb07 116
bgrissom 2:a57a5501152c 117 void cmd_S1(void) {
bgrissom 2:a57a5501152c 118 int i = 0;
bgrissom 2:a57a5501152c 119 int j = 0;
bgrissom 2:a57a5501152c 120
bgrissom 3:6f12c437ab88 121 gbbTRANS = 0; // FIXME
bgrissom 3:6f12c437ab88 122
bgrissom 2:a57a5501152c 123 if ( gSpiMode == true &&
bgrissom 2:a57a5501152c 124 gSpiPtr != NULL)
bgrissom 2:a57a5501152c 125 {
bgrissom 2:a57a5501152c 126 delete gSpiPtr;
bgrissom 2:a57a5501152c 127 gSpiPtr = NULL;
bgrissom 2:a57a5501152c 128 gSpiMode = false;
bgrissom 2:a57a5501152c 129 }
bgrissom 1:256d7a2f8391 130
bgrissom 2:a57a5501152c 131 DigitalOut bbSCK (D13); // bit bang clock
bgrissom 2:a57a5501152c 132
bgrissom 3:6f12c437ab88 133 bbSCK = 0; // Start off/low
bgrissom 3:6f12c437ab88 134 gbbTRANS = 1; // Set high
bgrissom 2:a57a5501152c 135
bgrissom 2:a57a5501152c 136 // Loop 6 times = 3 clock cycles
bgrissom 2:a57a5501152c 137 for (j=0; j<6; j++) { // Always use an even number here!
bgrissom 2:a57a5501152c 138 // The order of these two lines matter!
bgrissom 2:a57a5501152c 139 i == 0 ? i = 1 : i = 0; // Toggle i
bgrissom 2:a57a5501152c 140 i == 0 ? bbSCK = 0 : bbSCK = 1; // Set SCK to the same value as i
bgrissom 0:b0f98b83cb07 141 }
bgrissom 3:6f12c437ab88 142 gbbTRANS = 0; // Set low
bgrissom 2:a57a5501152c 143 }
bgrissom 2:a57a5501152c 144
bgrissom 2:a57a5501152c 145
bgrissom 5:9a662dec2ddb 146 /* USED FOR THE F030 BOARD
bgrissom 3:6f12c437ab88 147 // This code is based off:
bgrissom 3:6f12c437ab88 148 // mbed/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F030R8/pwmout_api.c pwmout_period_us()
bgrissom 5:9a662dec2ddb 149 void pwmout_period_ns_NOT_USED(pwmout_t* obj, int us) {
bgrissom 3:6f12c437ab88 150 TIM_TypeDef *tim = (TIM_TypeDef *)(obj->pwm);
bgrissom 3:6f12c437ab88 151 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
bgrissom 3:6f12c437ab88 152 float dc = pwmout_read(obj);
bgrissom 3:6f12c437ab88 153
bgrissom 3:6f12c437ab88 154 TIM_Cmd(tim, DISABLE);
bgrissom 3:6f12c437ab88 155
bgrissom 3:6f12c437ab88 156 obj->period = us;
bgrissom 3:6f12c437ab88 157
bgrissom 3:6f12c437ab88 158 TIM_TimeBaseStructure.TIM_Period = obj->period - 1;
bgrissom 3:6f12c437ab88 159 // Orig code: TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t)(SystemCoreClock / 1000000) - 1; // 1 µs tick
bgrissom 3:6f12c437ab88 160 TIM_TimeBaseStructure.TIM_Prescaler = 0; // BAG 1 ns tick (?)
bgrissom 3:6f12c437ab88 161 TIM_TimeBaseStructure.TIM_ClockDivision = 0;
bgrissom 3:6f12c437ab88 162 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
bgrissom 3:6f12c437ab88 163 TIM_TimeBaseInit(tim, &TIM_TimeBaseStructure);
bgrissom 3:6f12c437ab88 164
bgrissom 3:6f12c437ab88 165 // Set duty cycle again
bgrissom 3:6f12c437ab88 166 pwmout_write(obj, dc);
bgrissom 3:6f12c437ab88 167
bgrissom 3:6f12c437ab88 168 TIM_ARRPreloadConfig(tim, ENABLE);
bgrissom 3:6f12c437ab88 169
bgrissom 3:6f12c437ab88 170 TIM_Cmd(tim, ENABLE);
bgrissom 3:6f12c437ab88 171 }
bgrissom 5:9a662dec2ddb 172 */
bgrissom 5:9a662dec2ddb 173
bgrissom 5:9a662dec2ddb 174
bgrissom 6:e4da8955cf65 175 static TIM_HandleTypeDef TimHandleBAG;
bgrissom 5:9a662dec2ddb 176
bgrissom 6:e4da8955cf65 177 void pwmout_write_BAG(pwmout_t* obj, float value) {
bgrissom 6:e4da8955cf65 178 TIM_OC_InitTypeDef sConfig;
bgrissom 6:e4da8955cf65 179 int channel = 0;
bgrissom 6:e4da8955cf65 180 int complementary_channel = 0;
bgrissom 6:e4da8955cf65 181
bgrissom 6:e4da8955cf65 182 TimHandleBAG.Instance = (TIM_TypeDef *)(obj->pwm);
bgrissom 6:e4da8955cf65 183
bgrissom 6:e4da8955cf65 184 if (value < (float)0.0) {
bgrissom 6:e4da8955cf65 185 value = 0.0;
bgrissom 6:e4da8955cf65 186 } else if (value > (float)1.0) {
bgrissom 6:e4da8955cf65 187 value = 1.0;
bgrissom 6:e4da8955cf65 188 }
bgrissom 6:e4da8955cf65 189
bgrissom 6:e4da8955cf65 190 obj->pulse = (uint32_t)((float)obj->period * value);
bgrissom 6:e4da8955cf65 191
bgrissom 6:e4da8955cf65 192 // Configure channels
bgrissom 6:e4da8955cf65 193 sConfig.OCMode = TIM_OCMODE_PWM1;
bgrissom 6:e4da8955cf65 194 sConfig.Pulse = obj->pulse;
bgrissom 6:e4da8955cf65 195 sConfig.OCPolarity = TIM_OCPOLARITY_HIGH;
bgrissom 6:e4da8955cf65 196 sConfig.OCNPolarity = TIM_OCNPOLARITY_HIGH;
bgrissom 6:e4da8955cf65 197 sConfig.OCFastMode = TIM_OCFAST_DISABLE;
bgrissom 6:e4da8955cf65 198 sConfig.OCIdleState = TIM_OCIDLESTATE_RESET;
bgrissom 6:e4da8955cf65 199 sConfig.OCNIdleState = TIM_OCNIDLESTATE_RESET;
bgrissom 6:e4da8955cf65 200
bgrissom 6:e4da8955cf65 201 switch (obj->pin) {
bgrissom 6:e4da8955cf65 202 // Channels 1
bgrissom 6:e4da8955cf65 203 case PA_2:
bgrissom 6:e4da8955cf65 204 case PA_4:
bgrissom 6:e4da8955cf65 205 case PA_6:
bgrissom 6:e4da8955cf65 206 case PA_7:
bgrissom 6:e4da8955cf65 207 case PA_8:
bgrissom 6:e4da8955cf65 208 case PB_1:
bgrissom 6:e4da8955cf65 209 case PB_4:
bgrissom 6:e4da8955cf65 210 case PB_8:
bgrissom 6:e4da8955cf65 211 case PB_9:
bgrissom 6:e4da8955cf65 212 case PB_14:
bgrissom 6:e4da8955cf65 213 case PC_6:
bgrissom 6:e4da8955cf65 214 channel = TIM_CHANNEL_1;
bgrissom 6:e4da8955cf65 215 break;
bgrissom 6:e4da8955cf65 216 // Channels 1N
bgrissom 6:e4da8955cf65 217 case PA_1:
bgrissom 6:e4da8955cf65 218 case PB_6:
bgrissom 6:e4da8955cf65 219 case PB_7:
bgrissom 6:e4da8955cf65 220 case PB_13:
bgrissom 6:e4da8955cf65 221 channel = TIM_CHANNEL_1;
bgrissom 6:e4da8955cf65 222 complementary_channel = 1;
bgrissom 6:e4da8955cf65 223 break;
bgrissom 6:e4da8955cf65 224 // Channels 2
bgrissom 6:e4da8955cf65 225 case PA_3:
bgrissom 6:e4da8955cf65 226 case PA_9:
bgrissom 6:e4da8955cf65 227 case PB_5:
bgrissom 6:e4da8955cf65 228 case PB_15:
bgrissom 6:e4da8955cf65 229 case PC_7:
bgrissom 6:e4da8955cf65 230 channel = TIM_CHANNEL_2;
bgrissom 6:e4da8955cf65 231 break;
bgrissom 6:e4da8955cf65 232 // Channels 3
bgrissom 6:e4da8955cf65 233 case PA_10:
bgrissom 6:e4da8955cf65 234 case PB_0:
bgrissom 6:e4da8955cf65 235 case PC_8:
bgrissom 6:e4da8955cf65 236 channel = TIM_CHANNEL_3;
bgrissom 6:e4da8955cf65 237 break;
bgrissom 6:e4da8955cf65 238 // Channels 4
bgrissom 6:e4da8955cf65 239 case PA_11:
bgrissom 6:e4da8955cf65 240 case PC_9:
bgrissom 6:e4da8955cf65 241 channel = TIM_CHANNEL_4;
bgrissom 6:e4da8955cf65 242 break;
bgrissom 6:e4da8955cf65 243 default:
bgrissom 6:e4da8955cf65 244 return;
bgrissom 6:e4da8955cf65 245 }
bgrissom 6:e4da8955cf65 246
bgrissom 6:e4da8955cf65 247 HAL_TIM_PWM_ConfigChannel(&TimHandleBAG, &sConfig, channel);
bgrissom 6:e4da8955cf65 248
bgrissom 6:e4da8955cf65 249 if (complementary_channel) {
bgrissom 6:e4da8955cf65 250 HAL_TIMEx_PWMN_Start(&TimHandleBAG, channel);
bgrissom 6:e4da8955cf65 251 } else {
bgrissom 6:e4da8955cf65 252 HAL_TIM_PWM_Start(&TimHandleBAG, channel);
bgrissom 6:e4da8955cf65 253 }
bgrissom 6:e4da8955cf65 254 }
bgrissom 6:e4da8955cf65 255
bgrissom 6:e4da8955cf65 256
bgrissom 5:9a662dec2ddb 257 void pwmout_period_ns(pwmout_t* obj, int us) {
bgrissom 6:e4da8955cf65 258 TimHandleBAG.Instance = (TIM_TypeDef *)(obj->pwm);
bgrissom 5:9a662dec2ddb 259
bgrissom 5:9a662dec2ddb 260 float dc = pwmout_read(obj);
bgrissom 5:9a662dec2ddb 261
bgrissom 6:e4da8955cf65 262 __HAL_TIM_DISABLE(&TimHandleBAG);
bgrissom 5:9a662dec2ddb 263
bgrissom 5:9a662dec2ddb 264 // Update the SystemCoreClock variable
bgrissom 5:9a662dec2ddb 265 SystemCoreClockUpdate();
bgrissom 5:9a662dec2ddb 266
bgrissom 6:e4da8955cf65 267 TimHandleBAG.Init.Period = us - 1;
bgrissom 6:e4da8955cf65 268 // BAG Orig: TimHandle.Init.Prescaler = (uint16_t)(SystemCoreClock / 1000000) - 1; // 1 µs tick
bgrissom 6:e4da8955cf65 269 TimHandleBAG.Init.Prescaler = 0; // BAG 1 ns tick (?)
bgrissom 6:e4da8955cf65 270 TimHandleBAG.Init.ClockDivision = 0;
bgrissom 6:e4da8955cf65 271 TimHandleBAG.Init.CounterMode = TIM_COUNTERMODE_UP;
bgrissom 6:e4da8955cf65 272 HAL_TIM_PWM_Init(&TimHandleBAG);
bgrissom 5:9a662dec2ddb 273
bgrissom 5:9a662dec2ddb 274 // Set duty cycle again
bgrissom 6:e4da8955cf65 275 pwmout_write_BAG(obj, dc);
bgrissom 5:9a662dec2ddb 276
bgrissom 5:9a662dec2ddb 277 // Save for future use
bgrissom 5:9a662dec2ddb 278 obj->period = us;
bgrissom 5:9a662dec2ddb 279
bgrissom 6:e4da8955cf65 280 __HAL_TIM_ENABLE(&TimHandleBAG);
bgrissom 5:9a662dec2ddb 281 }