mirror of
https://github.com/arduino/Arduino.git
synced 2025-01-29 18:52:13 +01:00
Fixed problems with analogWrite(...) for pins using Timer Counter
This commit is contained in:
parent
301585f1fc
commit
0c09b5d443
@ -151,24 +151,34 @@ uint32_t analogRead(uint32_t ulPin)
|
||||
return ulValue;
|
||||
}
|
||||
|
||||
static void TC_SetRA(Tc *tc, uint32_t chan, uint32_t v )
|
||||
static void TC_SetRA(Tc *tc, uint32_t chan, uint32_t v)
|
||||
{
|
||||
tc->TC_CHANNEL[chan].TC_RA = v;
|
||||
}
|
||||
|
||||
static void TC_SetRB(Tc *tc, uint32_t chan, uint32_t v )
|
||||
static void TC_SetRB(Tc *tc, uint32_t chan, uint32_t v)
|
||||
{
|
||||
tc->TC_CHANNEL[chan].TC_RB = v;
|
||||
}
|
||||
|
||||
static void TC_SetRC(Tc *tc, uint32_t chan, uint32_t v )
|
||||
static void TC_SetRC(Tc *tc, uint32_t chan, uint32_t v)
|
||||
{
|
||||
tc->TC_CHANNEL[chan].TC_RC = v;
|
||||
}
|
||||
|
||||
static void TC_SetCMR_ChannelA(Tc *tc, uint32_t chan, uint32_t v)
|
||||
{
|
||||
tc->TC_CHANNEL[chan].TC_CMR = (tc->TC_CHANNEL[chan].TC_CMR & 0xFFF0FFFF) | v;
|
||||
}
|
||||
|
||||
static void TC_SetCMR_ChannelB(Tc *tc, uint32_t chan, uint32_t v)
|
||||
{
|
||||
tc->TC_CHANNEL[chan].TC_CMR = (tc->TC_CHANNEL[chan].TC_CMR & 0xF0FFFFFF) | v;
|
||||
}
|
||||
|
||||
static uint8_t PWMEnabled = 0;
|
||||
static uint8_t pinEnabled[PINS_COUNT];
|
||||
static uint8_t TCChanEnabled[] = {0, 0, 0};
|
||||
static uint8_t TCChanEnabled[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
void analogOutputInit(void) {
|
||||
uint8_t i;
|
||||
@ -210,38 +220,52 @@ void analogWrite(uint32_t ulPin, uint32_t ulValue) {
|
||||
}
|
||||
|
||||
if ((attr & PIN_ATTR_TIMER) == PIN_ATTR_TIMER) {
|
||||
// We use MCLK/2 => 96Mhz/2 => 48Mhz as clock.
|
||||
// To get 1KHz we should use 48000 as TC
|
||||
// 48Mhz/48000 = 1KHz
|
||||
// We use MCLK/2 as clock.
|
||||
const uint32_t TC = VARIANT_MCK / 2 / TC_FREQUENCY;
|
||||
|
||||
// Map value to Timer ranges 0..255=>0..48000
|
||||
// Map value to Timer ranges 0..255 => 0..TC
|
||||
ulValue = ulValue * TC;
|
||||
ulValue = ulValue / TC_MAX_DUTY_CYCLE;
|
||||
|
||||
// Setup Timer for this pin
|
||||
ETCChannel channel = g_APinDescription[ulPin].ulTCChannel;
|
||||
static const uint32_t channelToChNo[] = { 0, 0, 1, 1, 2, 2 };
|
||||
static const uint32_t channelToAB[] = { 1, 0, 1, 0, 1, 0 };
|
||||
static const uint32_t channelToChNo[] = { 0, 0, 1, 1, 2, 2, 0, 0, 1, 1, 2, 2, 0, 0, 1, 1, 2, 2 };
|
||||
static const uint32_t channelToAB[] = { 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 };
|
||||
static const Tc *channelToTC[] = {
|
||||
TC0, TC0, TC0, TC0, TC0, TC0,
|
||||
TC1, TC1, TC1, TC1, TC1, TC1,
|
||||
TC2, TC2, TC2, TC2, TC2, TC2 };
|
||||
static const uint32_t channelToId[] = { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8 };
|
||||
uint32_t chNo = channelToChNo[channel];
|
||||
uint32_t chA = channelToAB[channel];
|
||||
uint32_t chA = channelToAB[channel];
|
||||
Tc *chTC = channelToTC[channel];
|
||||
uint32_t interfaceID = channelToId[channel];
|
||||
|
||||
if (!TCChanEnabled[chNo]) {
|
||||
pmc_enable_periph_clk(TC_INTERFACE_ID + chNo);
|
||||
TC_Configure(TC_INTERFACE, chNo,
|
||||
TC_CMR_TCCLKS_TIMER_CLOCK1 |
|
||||
TC_CMR_WAVE |
|
||||
TC_CMR_WAVSEL_UP_RC |
|
||||
TC_CMR_ACPA_CLEAR | // RA Compare Effect on OA: clear
|
||||
TC_CMR_ACPC_SET | // RC Compare Effect on OA: set
|
||||
TC_CMR_BCPB_CLEAR | // RB Compare Effect on OB: clear
|
||||
TC_CMR_BCPC_SET); // RC Compare Effect on OB: set
|
||||
TC_SetRC(TC_INTERFACE, chNo, TC);
|
||||
if (!TCChanEnabled[interfaceID]) {
|
||||
pmc_enable_periph_clk(TC_INTERFACE_ID + interfaceID);
|
||||
TC_Configure(chTC, chNo,
|
||||
TC_CMR_TCCLKS_TIMER_CLOCK1 |
|
||||
TC_CMR_WAVE | // Waveform mode
|
||||
TC_CMR_WAVSEL_UP_RC | // Counter running up and reset when equals to RC
|
||||
TC_CMR_EEVT_XC0 | // Set external events from XC0 (this setup TIOB as output)
|
||||
TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_CLEAR |
|
||||
TC_CMR_BCPB_CLEAR | TC_CMR_BCPC_CLEAR);
|
||||
TC_SetRC(chTC, chNo, TC);
|
||||
}
|
||||
if (ulValue == 0) {
|
||||
if (chA)
|
||||
TC_SetCMR_ChannelA(chTC, chNo, TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_CLEAR);
|
||||
else
|
||||
TC_SetCMR_ChannelB(chTC, chNo, TC_CMR_BCPB_CLEAR | TC_CMR_BCPC_CLEAR);
|
||||
} else {
|
||||
if (chA) {
|
||||
TC_SetRA(chTC, chNo, ulValue);
|
||||
TC_SetCMR_ChannelA(chTC, chNo, TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_SET);
|
||||
} else {
|
||||
TC_SetRB(chTC, chNo, ulValue);
|
||||
TC_SetCMR_ChannelB(chTC, chNo, TC_CMR_BCPB_CLEAR | TC_CMR_BCPC_SET);
|
||||
}
|
||||
}
|
||||
if (chA)
|
||||
TC_SetRA(TC_INTERFACE, chNo, ulValue);
|
||||
else
|
||||
TC_SetRB(TC_INTERFACE, chNo, ulValue);
|
||||
if (!pinEnabled[ulPin]) {
|
||||
PIO_Configure(g_APinDescription[ulPin].pPort,
|
||||
g_APinDescription[ulPin].ulPinType,
|
||||
@ -249,14 +273,14 @@ void analogWrite(uint32_t ulPin, uint32_t ulValue) {
|
||||
g_APinDescription[ulPin].ulPinConfiguration);
|
||||
pinEnabled[ulPin] = 1;
|
||||
}
|
||||
if (!TCChanEnabled[chNo]) {
|
||||
TC_Start(TC_INTERFACE, chNo);
|
||||
TCChanEnabled[chNo] = 1;
|
||||
if (!TCChanEnabled[interfaceID]) {
|
||||
TC_Start(chTC, chNo);
|
||||
TCChanEnabled[interfaceID] = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Default to digital write
|
||||
// Defaults to digital write
|
||||
pinMode(ulPin, OUTPUT);
|
||||
if (ulValue < 128)
|
||||
digitalWrite(ulPin, LOW);
|
||||
|
@ -140,7 +140,7 @@ extern const PinDescription g_APinDescription[]=
|
||||
{ PIOC, PIO_PC26B_TIOB6, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_TIMER), NO_ADC, NO_ADC, NO_PWM, TC2_CHB6 }, // TIOB6
|
||||
|
||||
// 5
|
||||
{ PIOC, PIO_PC25B_TIOA6, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_TIMER), NO_ADC, NO_ADC, NO_PWM, TC0_CHA2 }, // TIOA6
|
||||
{ PIOC, PIO_PC25B_TIOA6, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_TIMER), NO_ADC, NO_ADC, NO_PWM, TC2_CHA6 }, // TIOA6
|
||||
{ PIOC, PIO_PC24B_PWML7, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), NO_ADC, NO_ADC, PWM_CH7, NO_TC }, // PWML7
|
||||
{ PIOC, PIO_PC23B_PWML6, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), NO_ADC, NO_ADC, PWM_CH6, NO_TC }, // PWML6
|
||||
{ PIOC, PIO_PC22B_PWML5, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), NO_ADC, NO_ADC, PWM_CH5, NO_TC }, // PWML5
|
||||
@ -151,7 +151,7 @@ extern const PinDescription g_APinDescription[]=
|
||||
{ PIOD, PIO_PD8B_TIOB8, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_TIMER), NO_ADC, NO_ADC, NO_PWM, TC2_CHB8 }, // TIOB8
|
||||
|
||||
// 13 - AMBER LED
|
||||
{ PIOB, PIO_PB27B_TIOB0, ID_PIOB, PIO_OUTPUT_0, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_TIMER), NO_ADC, NO_ADC, NO_PWM, TC0_CHB0 }, // TIOB0
|
||||
{ PIOB, PIO_PB27B_TIOB0, ID_PIOB, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_TIMER), NO_ADC, NO_ADC, NO_PWM, TC0_CHB0 }, // TIOB0
|
||||
|
||||
// 14/15 - USART2 (Serial4)
|
||||
{ PIOD, PIO_PD4B_TXD3, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NO_PWM, NO_TC }, // TXD3
|
||||
|
Loading…
x
Reference in New Issue
Block a user