MATSU-bed(LPC1549)でPWMを4つ以上出すプログラム

Dependents:   servo_controller_1549

Committer:
hardtail
Date:
Wed Apr 20 08:12:06 2016 +0000
Revision:
0:64b18a3829f1
Child:
1:aefedd6b2a6f
??????????LPC1549?PWM?4?????????????

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hardtail 0:64b18a3829f1 1 /* mbed Microcontroller Library
hardtail 0:64b18a3829f1 2 * Copyright (c) 2006-2013 ARM Limited
hardtail 0:64b18a3829f1 3 *
hardtail 0:64b18a3829f1 4 * Licensed under the Apache License, Version 2.0 (the "License");
hardtail 0:64b18a3829f1 5 * you may not use this file except in compliance with the License.
hardtail 0:64b18a3829f1 6 * You may obtain a copy of the License at
hardtail 0:64b18a3829f1 7 *
hardtail 0:64b18a3829f1 8 * http://www.apache.org/licenses/LICENSE-2.0
hardtail 0:64b18a3829f1 9 *
hardtail 0:64b18a3829f1 10 * Unless required by applicable law or agreed to in writing, software
hardtail 0:64b18a3829f1 11 * distributed under the License is distributed on an "AS IS" BASIS,
hardtail 0:64b18a3829f1 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
hardtail 0:64b18a3829f1 13 * See the License for the specific language governing permissions and
hardtail 0:64b18a3829f1 14 * limitations under the License.
hardtail 0:64b18a3829f1 15 */
hardtail 0:64b18a3829f1 16 #include "mbed_assert.h"
hardtail 0:64b18a3829f1 17 #include "pwm_all_api.h"
hardtail 0:64b18a3829f1 18 #include "cmsis.h"
hardtail 0:64b18a3829f1 19 #include "pinmap.h"
hardtail 0:64b18a3829f1 20 #include "mbed_error.h"
hardtail 0:64b18a3829f1 21
hardtail 0:64b18a3829f1 22 static LPC_SCT0_Type *SCTs[4] = {
hardtail 0:64b18a3829f1 23 (LPC_SCT0_Type*)LPC_SCT0,
hardtail 0:64b18a3829f1 24 (LPC_SCT0_Type*)LPC_SCT1,
hardtail 0:64b18a3829f1 25 (LPC_SCT0_Type*)LPC_SCT2,
hardtail 0:64b18a3829f1 26 (LPC_SCT0_Type*)LPC_SCT3,
hardtail 0:64b18a3829f1 27 };
hardtail 0:64b18a3829f1 28
hardtail 0:64b18a3829f1 29 // bit flags for used SCTs
hardtail 0:64b18a3829f1 30 static unsigned char sct_used = 0;
hardtail 0:64b18a3829f1 31 static int get_available_sct(void) {
hardtail 0:64b18a3829f1 32 int i;
hardtail 0:64b18a3829f1 33 for (i=0; i<4; i++) {
hardtail 0:64b18a3829f1 34 if ((sct_used & (1 << i)) == 0)
hardtail 0:64b18a3829f1 35 return i;
hardtail 0:64b18a3829f1 36 }
hardtail 0:64b18a3829f1 37 return -1;
hardtail 0:64b18a3829f1 38 }
hardtail 0:64b18a3829f1 39
hardtail 0:64b18a3829f1 40 void pwmout_init(pwmout_t* obj, PinName pin) {
hardtail 0:64b18a3829f1 41 MBED_ASSERT(pin != (uint32_t)NC);
hardtail 0:64b18a3829f1 42
hardtail 0:64b18a3829f1 43 int sct_n = get_available_sct();
hardtail 0:64b18a3829f1 44 if (sct_n == -1) {
hardtail 0:64b18a3829f1 45 error("No available SCT");
hardtail 0:64b18a3829f1 46 }
hardtail 0:64b18a3829f1 47
hardtail 0:64b18a3829f1 48 sct_used |= (1 << sct_n);
hardtail 0:64b18a3829f1 49 obj->pwm = SCTs[sct_n];
hardtail 0:64b18a3829f1 50 obj->pwm_ch = sct_n;
hardtail 0:64b18a3829f1 51
hardtail 0:64b18a3829f1 52 LPC_SCT0_Type* pwm = obj->pwm;
hardtail 0:64b18a3829f1 53
hardtail 0:64b18a3829f1 54 // Enable the SCT clock
hardtail 0:64b18a3829f1 55 LPC_SYSCON->SYSAHBCLKCTRL1 |= (1 << (obj->pwm_ch + 2));
hardtail 0:64b18a3829f1 56
hardtail 0:64b18a3829f1 57 // Clear peripheral reset the SCT:
hardtail 0:64b18a3829f1 58 LPC_SYSCON->PRESETCTRL1 |= (1 << (obj->pwm_ch + 2));
hardtail 0:64b18a3829f1 59 LPC_SYSCON->PRESETCTRL1 &= ~(1 << (obj->pwm_ch + 2));
hardtail 0:64b18a3829f1 60
hardtail 0:64b18a3829f1 61 switch(obj->pwm_ch) {
hardtail 0:64b18a3829f1 62 case 0:
hardtail 0:64b18a3829f1 63 // SCT0_OUT0
hardtail 0:64b18a3829f1 64 LPC_SWM->PINASSIGN[7] &= ~0x0000FF00;
hardtail 0:64b18a3829f1 65 LPC_SWM->PINASSIGN[7] |= (pin << 8);
hardtail 0:64b18a3829f1 66 break;
hardtail 0:64b18a3829f1 67 case 1:
hardtail 0:64b18a3829f1 68 // SCT1_OUT0
hardtail 0:64b18a3829f1 69 LPC_SWM->PINASSIGN[8] &= ~0x000000FF;
hardtail 0:64b18a3829f1 70 LPC_SWM->PINASSIGN[8] |= (pin);
hardtail 0:64b18a3829f1 71 break;
hardtail 0:64b18a3829f1 72 case 2:
hardtail 0:64b18a3829f1 73 // SCT2_OUT0
hardtail 0:64b18a3829f1 74 LPC_SWM->PINASSIGN[8] &= ~0xFF000000;
hardtail 0:64b18a3829f1 75 LPC_SWM->PINASSIGN[8] |= (pin << 24);
hardtail 0:64b18a3829f1 76 break;
hardtail 0:64b18a3829f1 77 case 3:
hardtail 0:64b18a3829f1 78 // SCT3_OUT0
hardtail 0:64b18a3829f1 79 LPC_SWM->PINASSIGN[9] &= ~0x00FF0000;
hardtail 0:64b18a3829f1 80 LPC_SWM->PINASSIGN[9] |= (pin << 16);
hardtail 0:64b18a3829f1 81 break;
hardtail 0:64b18a3829f1 82 default:
hardtail 0:64b18a3829f1 83 break;
hardtail 0:64b18a3829f1 84 }
hardtail 0:64b18a3829f1 85
hardtail 0:64b18a3829f1 86 // Unified 32-bit counter, autolimit
hardtail 0:64b18a3829f1 87 pwm->CONFIG |= ((0x3 << 17) | 0x01);
hardtail 0:64b18a3829f1 88
hardtail 0:64b18a3829f1 89 // halt and clear the counter
hardtail 0:64b18a3829f1 90 pwm->CTRL |= (1 << 2) | (1 << 3);
hardtail 0:64b18a3829f1 91
hardtail 0:64b18a3829f1 92 // System Clock -> us_ticker (1)MHz
hardtail 0:64b18a3829f1 93 pwm->CTRL &= ~(0x7F << 5);
hardtail 0:64b18a3829f1 94 pwm->CTRL |= (((SystemCoreClock/1000000 - 1) & 0x7F) << 5);
hardtail 0:64b18a3829f1 95
hardtail 0:64b18a3829f1 96 // Match reload register
hardtail 0:64b18a3829f1 97 pwm->MATCHREL0 = 20000; // 20ms
hardtail 0:64b18a3829f1 98 pwm->MATCHREL1 = (pwm->MATCHREL0 / 4); // 50% duty
hardtail 0:64b18a3829f1 99
hardtail 0:64b18a3829f1 100 pwm->OUT0_SET = (1 << 0); // event 0
hardtail 0:64b18a3829f1 101 pwm->OUT0_CLR = (1 << 1); // event 1
hardtail 0:64b18a3829f1 102
hardtail 0:64b18a3829f1 103 pwm->EV0_CTRL = (1 << 12);
hardtail 0:64b18a3829f1 104 pwm->EV0_STATE = 0xFFFFFFFF;
hardtail 0:64b18a3829f1 105 pwm->EV1_CTRL = (1 << 12) | (1 << 0);
hardtail 0:64b18a3829f1 106 pwm->EV1_STATE = 0xFFFFFFFF;
hardtail 0:64b18a3829f1 107
hardtail 0:64b18a3829f1 108 // unhalt the counter:
hardtail 0:64b18a3829f1 109 // - clearing bit 2 of the CTRL register
hardtail 0:64b18a3829f1 110 pwm->CTRL &= ~(1 << 2);
hardtail 0:64b18a3829f1 111
hardtail 0:64b18a3829f1 112 // default to 20ms: standard for servos, and fine for e.g. brightness control
hardtail 0:64b18a3829f1 113 pwmout_period_ms(obj, 20);
hardtail 0:64b18a3829f1 114 pwmout_write (obj, 0);
hardtail 0:64b18a3829f1 115 }
hardtail 0:64b18a3829f1 116
hardtail 0:64b18a3829f1 117 void pwmout_free(pwmout_t* obj) {
hardtail 0:64b18a3829f1 118 // Disable the SCT clock
hardtail 0:64b18a3829f1 119 LPC_SYSCON->SYSAHBCLKCTRL1 &= ~(1 << (obj->pwm_ch + 2));
hardtail 0:64b18a3829f1 120 sct_used &= ~(1 << obj->pwm_ch);
hardtail 0:64b18a3829f1 121 }
hardtail 0:64b18a3829f1 122
hardtail 0:64b18a3829f1 123 void pwmout_write(pwmout_t* obj, float value) {
hardtail 0:64b18a3829f1 124 LPC_SCT0_Type* pwm = obj->pwm;
hardtail 0:64b18a3829f1 125 if (value < 0.0f) {
hardtail 0:64b18a3829f1 126 value = 0.0;
hardtail 0:64b18a3829f1 127 } else if (value > 1.0f) {
hardtail 0:64b18a3829f1 128 value = 1.0;
hardtail 0:64b18a3829f1 129 }
hardtail 0:64b18a3829f1 130 uint32_t t_on = (uint32_t)((float)(pwm->MATCHREL0) * value);
hardtail 0:64b18a3829f1 131 pwm->MATCHREL1 = t_on;
hardtail 0:64b18a3829f1 132 }
hardtail 0:64b18a3829f1 133
hardtail 0:64b18a3829f1 134 float pwmout_read(pwmout_t* obj) {
hardtail 0:64b18a3829f1 135 uint32_t t_off = obj->pwm->MATCHREL0;
hardtail 0:64b18a3829f1 136 uint32_t t_on = obj->pwm->MATCHREL1;
hardtail 0:64b18a3829f1 137 float v = (float)t_on/(float)t_off;
hardtail 0:64b18a3829f1 138 return (v > 1.0f) ? (1.0f) : (v);
hardtail 0:64b18a3829f1 139 }
hardtail 0:64b18a3829f1 140
hardtail 0:64b18a3829f1 141 void pwmout_period(pwmout_t* obj, float seconds) {
hardtail 0:64b18a3829f1 142 pwmout_period_us(obj, seconds * 1000000.0f);
hardtail 0:64b18a3829f1 143 }
hardtail 0:64b18a3829f1 144
hardtail 0:64b18a3829f1 145 void pwmout_period_ms(pwmout_t* obj, int ms) {
hardtail 0:64b18a3829f1 146 pwmout_period_us(obj, ms * 1000);
hardtail 0:64b18a3829f1 147 }
hardtail 0:64b18a3829f1 148
hardtail 0:64b18a3829f1 149 // Set the PWM period, keeping the duty cycle the same.
hardtail 0:64b18a3829f1 150 void pwmout_period_us(pwmout_t* obj, int us) {
hardtail 0:64b18a3829f1 151 LPC_SCT0_Type* pwm = obj->pwm;
hardtail 0:64b18a3829f1 152 uint32_t t_off = pwm->MATCHREL0;
hardtail 0:64b18a3829f1 153 uint32_t t_on = pwm->MATCHREL1;
hardtail 0:64b18a3829f1 154 float v = (float)t_on/(float)t_off;
hardtail 0:64b18a3829f1 155 pwm->MATCHREL0 = (uint32_t)us;
hardtail 0:64b18a3829f1 156 pwm->MATCHREL1 = (uint32_t)((float)us * (float)v);
hardtail 0:64b18a3829f1 157 }
hardtail 0:64b18a3829f1 158
hardtail 0:64b18a3829f1 159 void pwmout_pulsewidth(pwmout_t* obj, float seconds) {
hardtail 0:64b18a3829f1 160 pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
hardtail 0:64b18a3829f1 161 }
hardtail 0:64b18a3829f1 162
hardtail 0:64b18a3829f1 163 void pwmout_pulsewidth_ms(pwmout_t* obj, int ms) {
hardtail 0:64b18a3829f1 164 pwmout_pulsewidth_us(obj, ms * 1000);
hardtail 0:64b18a3829f1 165 }
hardtail 0:64b18a3829f1 166
hardtail 0:64b18a3829f1 167 void pwmout_pulsewidth_us(pwmout_t* obj, int us) {
hardtail 0:64b18a3829f1 168 obj->pwm->MATCHREL1 = (uint32_t)us;
hardtail 0:64b18a3829f1 169 }