PwmDAC is a library to run more the one PWM channel and channel updates at the time. Maximum PWM frequency is 48MHz. You can use for in example for rgb applications or as a multi channel dac with connected active lowpass. Written for mbed LPC1768. Not completly tested. I will upload my results as soon as possible. Although some deeper informations and LTSpice simulations
Dependents: DiscoTech filter_implement
PwmDAC.cpp
00001 #include "PwmDAC.h" 00002 #include "mbed.h" 00003 00004 void PwmDAC::init() { 00005 _allActive = true; 00006 _resolution = 255; 00007 _frequency = (double) SYS_CLK / _resolution; 00008 _period = 1 / _frequency; 00009 for(int i = 0; i < 6; i++) { 00010 _pulsewidth[i] = 0.0; 00011 _duty[i] = 0.0; 00012 _steps[i] = 0; 00013 } 00014 00015 LPC_SC->PCONP |= (1 << 6); // Bit 6 -> 1 == Poweron PWM1 00016 LPC_SC->PCLKSEL0 |= (1 << 12); // Bit 13/12 -> 0/1 == Full clock 96MHz 00017 LPC_PINCON->PINSEL4 |= (1 << 0) | (1 << 2) | (1 << 4) | (1 << 6) | (1 << 8) | (1 << 10); 00018 // PWM on ch. 1-6 p26 p25 p24 p23 p22 p21 00019 LPC_PINCON->PINMODE4 |= (2 << 0) | (2 << 2) | (2 << 4) | (2 << 6) | (2 << 8) | (2 << 10); 00020 // no pull up/ down p26 p25 p24 p23 p22 p21 00021 // 0 - pull up enabled 00022 // 1 - repeater mode enabled 00023 // 2 - no pull up/down 00024 // 3 - pull down enabled 00025 00026 LPC_PWM1->MCR = 2; // no reset, stop or interrupt on timer compare match 00027 // only TC reset on match with MR0 == new period of pwm cycle 00028 LPC_PWM1->CTCR |= (0 << 0); // PWM used in timer mode 00029 LPC_PWM1->PCR = 0; // all channels are single edge controlled, outputs disable 00030 LPC_PWM1->PCR |= (0x3F << 9); // Bit 14:9 -> 1 PWM outputs ch. 1-6 enabled 00031 LPC_PWM1->PR = 0; // no prescaling for PWM1 TC 00032 00033 MR[0] = &LPC_PWM1->MR0; 00034 MR[1] = &LPC_PWM1->MR1; 00035 MR[2] = &LPC_PWM1->MR2; 00036 MR[3] = &LPC_PWM1->MR3; 00037 MR[4] = &LPC_PWM1->MR4; 00038 MR[5] = &LPC_PWM1->MR5; 00039 MR[6] = &LPC_PWM1->MR6; 00040 00041 *MR[0] = _resolution; // period of 1 PWM cycle 00042 LPC_PWM1->LER |= (1 << 0); // update shadowregister, set cycle to output 00043 00044 for(int i = 1; i < 7; i++) { // update ch. 1-6 00045 *MR[i] = 0; 00046 } 00047 LPC_PWM1->LER |= (0x3F << 1); 00048 00049 LPC_PWM1->TCR |= (1 << 3) | (1 << 0); // enable PWM and Timer (PWM unit) 00050 // ==> output update from MR1-6 are load and 00051 // enabled with LPC_PWM1->LER Bit 6:1 set to "1" 00052 00053 } 00054 00055 void PwmDAC::deactivate(unsigned int ch) { 00056 if(ch < 6) { 00057 LPC_PINCON->PINSEL4 &= ~(1 << (ch + ch)); 00058 LPC_PINCON->PINMODE4 |= (3 << (ch + ch)); 00059 } 00060 else {// deactivate all 00061 LPC_PINCON->PINSEL4 &= 0xFFFFFB00; 00062 // PWM on ch. 0-5 p26 p25 p24 p23 p22 p21 00063 LPC_PINCON->PINMODE4 |= (3 << 0) | (3 << 2) | (3 << 4) | (3 << 6) | (3 << 8) | (3 << 10); 00064 } 00065 _allActive = false; 00066 } 00067 00068 void PwmDAC::activate(unsigned int ch) { 00069 if(ch < 6) { 00070 LPC_PINCON->PINSEL4 |= (1 << (ch + ch)); 00071 LPC_PINCON->PINMODE4 |= (2 << (ch + ch)); 00072 _allActive = false; 00073 } 00074 else {// activate all 00075 LPC_PINCON->PINSEL4 |= (1 << 0) | (1 << 2) | (1 << 4) | (1 << 6) | (1 << 8) | (1 << 10); 00076 // PWM on ch. 0-5 p26 p25 p24 p23 p22 p21 00077 LPC_PINCON->PINMODE4 |= (2 << 0) | (2 << 2) | (2 << 4) | (2 << 6) | (2 << 8) | (2 << 10); 00078 _allActive = true; 00079 } 00080 } 00081 00082 void PwmDAC::setFrequency(double frequency) { 00083 _frequency = frequency; 00084 _period = 1/frequency; 00085 _resolution = (uint32_t) ((double) SYS_CLK / frequency); 00086 00087 *MR[0] = _resolution; // period of 1 PWM cycle 00088 LPC_PWM1->LER |= (1 << 0); // update shadowregister, set cycle to output 00089 } 00090 00091 void PwmDAC::setPeriod(double seconds) { 00092 _frequency = 1/seconds; 00093 _period = seconds; 00094 _resolution = (uint32_t) ((double) SYS_CLK * seconds); 00095 00096 *MR[0] = _resolution; // period of 1 PWM cycle 00097 LPC_PWM1->LER |= (1 << 0); // update shadowregister, set cycle to output 00098 } 00099 00100 void PwmDAC::setResolution(uint32_t resolution) { 00101 _resolution = resolution; 00102 _frequency = (double) SYS_CLK / resolution; 00103 _period = 1 / _frequency; 00104 00105 *MR[0] = _resolution; // period of 1 PWM cycle 00106 LPC_PWM1->LER |= (1 << 0); // update shadowregister, set cycle to output 00107 } 00108 00109 void PwmDAC::updateDuty(double duty[]) { 00110 for(int i = 0; i < 6; i++) { 00111 if(duty[i] <= 100.0) { 00112 _duty[i] = duty[i]; 00113 _pulsewidth[i] = duty[i] / 100.0 * _period; 00114 _steps[i] = (uint32_t) ((double) SYS_CLK * _pulsewidth[i]); 00115 *MR[i+1] = _steps[i]; 00116 } 00117 } 00118 LPC_PWM1->LER |= (0x3F << 1); 00119 } 00120 00121 void PwmDAC::updatePulsewidth(double pulsewidth[]) { 00122 for(int i = 0; i < 6; i++) { 00123 if(pulsewidth[i] <= _period) { 00124 _duty[i] = pulsewidth[i] / _period; 00125 _pulsewidth[i] = pulsewidth[i]; 00126 _steps[i] = (uint32_t) ((double) SYS_CLK * pulsewidth[i]); 00127 *MR[i+1] = _steps[i]; 00128 } 00129 } 00130 LPC_PWM1->LER |= (0x3F << 1); 00131 } 00132 00133 void PwmDAC::updateSteps(uint32_t steps[]) { 00134 for(int i = 0; i < 6; i++) { 00135 if(steps[i] <= _resolution) { 00136 _duty[i] = (double) steps[i] / _resolution; 00137 _pulsewidth[i] = _duty[i] * _period; 00138 _steps[i] = steps[i]; 00139 *MR[i+1] = steps[i]; 00140 } 00141 } 00142 LPC_PWM1->LER |= (0x3F << 1); 00143 } 00144 00145 void PwmDAC::stop() { 00146 for(int i = 0; i < 6; i++) { 00147 *MR[i+1] = 0; 00148 } 00149 LPC_PWM1->LER |= (0x3F << 1); 00150 } 00151 00152 void PwmDAC::start() { 00153 for(int i = 0; i < 6; i++) { 00154 *MR[i+1] = _steps[i]; 00155 } 00156 LPC_PWM1->LER |= (0x3F << 1); 00157 }
Generated on Tue Jul 12 2022 22:09:34 by 1.7.2