Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-src by
pwmout_api.c
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2013 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 #include "pwmout_api.h" 00017 #include "cmsis.h" 00018 #include "pinmap.h" 00019 #include "error.h" 00020 00021 #define TCR_CNT_EN 0x00000001 00022 #define TCR_RESET 0x00000002 00023 00024 // PORT ID, PWM ID, Pin function 00025 static const PinMap PinMap_PWM[] = { 00026 {P1_18, PWM_1, 2}, 00027 {P1_20, PWM_2, 2}, 00028 {P1_21, PWM_3, 2}, 00029 {P1_23, PWM_4, 2}, 00030 {P1_24, PWM_5, 2}, 00031 {P1_26, PWM_6, 2}, 00032 {P2_0 , PWM_1, 1}, 00033 {P2_1 , PWM_2, 1}, 00034 {P2_2 , PWM_3, 1}, 00035 {P2_3 , PWM_4, 1}, 00036 {P2_4 , PWM_5, 1}, 00037 {P2_5 , PWM_6, 1}, 00038 {P3_25, PWM_2, 3}, 00039 {P3_26, PWM_3, 3}, 00040 {NC, NC, 0} 00041 }; 00042 00043 __IO uint32_t *PWM_MATCH[] = { 00044 &(LPC_PWM1->MR0), 00045 &(LPC_PWM1->MR1), 00046 &(LPC_PWM1->MR2), 00047 &(LPC_PWM1->MR3), 00048 &(LPC_PWM1->MR4), 00049 &(LPC_PWM1->MR5), 00050 &(LPC_PWM1->MR6) 00051 }; 00052 00053 #define TCR_PWM_EN 0x00000008 00054 00055 static unsigned int pwm_clock_mhz; 00056 00057 void pwmout_init(pwmout_t* obj, PinName pin) { 00058 // determine the channel 00059 PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM); 00060 if (pwm == (uint32_t)NC) 00061 error("PwmOut pin mapping failed"); 00062 00063 obj->pwm = pwm; 00064 obj->MR = PWM_MATCH[pwm]; 00065 00066 // ensure the power is on 00067 LPC_SC->PCONP |= 1 << 6; 00068 00069 // ensure clock to /4 00070 LPC_SC->PCLKSEL0 &= ~(0x3 << 12); // pclk = /4 00071 LPC_PWM1->PR = 0; // no pre-scale 00072 00073 // ensure single PWM mode 00074 LPC_PWM1->MCR = 1 << 1; // reset TC on match 0 00075 00076 // enable the specific PWM output 00077 LPC_PWM1->PCR |= 1 << (8 + pwm); 00078 00079 pwm_clock_mhz = SystemCoreClock / 4000000; 00080 00081 // default to 20ms: standard for servos, and fine for e.g. brightness control 00082 pwmout_period_ms(obj, 20); 00083 pwmout_write (obj, 0); 00084 00085 // Wire pinout 00086 pinmap_pinout(pin, PinMap_PWM); 00087 } 00088 00089 void pwmout_free(pwmout_t* obj) { 00090 // [TODO] 00091 } 00092 00093 void pwmout_write(pwmout_t* obj, float value) { 00094 if (value < 0.0f) { 00095 value = 0.0; 00096 } else if (value > 1.0f) { 00097 value = 1.0; 00098 } 00099 00100 // set channel match to percentage 00101 uint32_t v = (uint32_t)((float)(LPC_PWM1->MR0) * value); 00102 00103 // workaround for PWM1[1] - Never make it equal MR0, else we get 1 cycle dropout 00104 if (v == LPC_PWM1->MR0) { 00105 v++; 00106 } 00107 00108 *obj->MR = v; 00109 00110 // accept on next period start 00111 LPC_PWM1->LER |= 1 << obj->pwm; 00112 } 00113 00114 float pwmout_read(pwmout_t* obj) { 00115 float v = (float)(*obj->MR) / (float)(LPC_PWM1->MR0); 00116 return (v > 1.0f) ? (1.0f) : (v); 00117 } 00118 00119 void pwmout_period(pwmout_t* obj, float seconds) { 00120 pwmout_period_us(obj, seconds * 1000000.0f); 00121 } 00122 00123 void pwmout_period_ms(pwmout_t* obj, int ms) { 00124 pwmout_period_us(obj, ms * 1000); 00125 } 00126 00127 // Set the PWM period, keeping the duty cycle the same. 00128 void pwmout_period_us(pwmout_t* obj, int us) { 00129 // calculate number of ticks 00130 uint32_t ticks = pwm_clock_mhz * us; 00131 00132 // set reset 00133 LPC_PWM1->TCR = TCR_RESET; 00134 00135 // set the global match register 00136 LPC_PWM1->MR0 = ticks; 00137 00138 // Scale the pulse width to preserve the duty ratio 00139 if (LPC_PWM1->MR0 > 0) { 00140 *obj->MR = (*obj->MR * ticks) / LPC_PWM1->MR0; 00141 } 00142 00143 // set the channel latch to update value at next period start 00144 LPC_PWM1->LER |= 1 << 0; 00145 00146 // enable counter and pwm, clear reset 00147 LPC_PWM1->TCR = TCR_CNT_EN | TCR_PWM_EN; 00148 } 00149 00150 void pwmout_pulsewidth(pwmout_t* obj, float seconds) { 00151 pwmout_pulsewidth_us(obj, seconds * 1000000.0f); 00152 } 00153 00154 void pwmout_pulsewidth_ms(pwmout_t* obj, int ms) { 00155 pwmout_pulsewidth_us(obj, ms * 1000); 00156 } 00157 00158 void pwmout_pulsewidth_us(pwmout_t* obj, int us) { 00159 // calculate number of ticks 00160 uint32_t v = pwm_clock_mhz * us; 00161 00162 // workaround for PWM1[1] - Never make it equal MR0, else we get 1 cycle dropout 00163 if (v == LPC_PWM1->MR0) { 00164 v++; 00165 } 00166 00167 // set the match register value 00168 *obj->MR = v; 00169 00170 // set the channel latch to update value at next period start 00171 LPC_PWM1->LER |= 1 << obj->pwm; 00172 }
Generated on Tue Jul 12 2022 13:47:01 by
1.7.2
