the project: I want to dim an RGB-LED with PWM (MCU: STM8S103). The amount of dimming should be received as a datastream over DMX which is implemented via serial.
the problem: When I send data on a specific channel, the data is received, but there's a shift in the channel... So if I send data on channel 0 (DMXchannel 1), the channel which receives the data is drifting from 0 to 511, or even no data is received. So the system seem to be very unstable. Does someone know what could be the problem? here is my sktech:
/*
18.4.24, DMX sketch
DMX receiving-sketch
based on the uart loopback example: https://registry.platformio.org/platforms/platformio/ststm8/examples/spl-uart-loopback
PWM implementation based on: https://embedded-lab.com/blog/starting-stm8-microcontrollers/20/
*/
/* Includes ------------------------------------------------------------------*/
#include <Arduino.h>
/* Defines -----------------------------------------------------------------*/
#define DMX_CHANNEL_COUNT 512 //all 512 DMX channel
#define DMX_CHANNEL_LED 1 //DMX Data on channel 1
volatile bool dmxMessageStarted = false; //true if databytes are received
volatile bool dataFree = false; //true if nothing is written in array by interrupt
volatile uint8_t dmxData[DMX_CHANNEL_COUNT]; //array to store DMX data in
volatile uint16_t dmxIndex = 0;
/* Private function prototypes -----------------------------------------------*/
static void CLK_Config(void);
static void UART_Config(void);
void GPIO_setup(void);
void TIM2_setup(void);
void main(void)
{
pinMode(LED_BUILTIN, OUTPUT);
CLK_Config(); //configure prescaler
GPIO_setup();
TIM2_setup();
UART_Config(); //configure UART
while(TRUE)
{
if(dataFree){ //if data array is not used by interrupt
TIM2_SetCompare1(dmxData[DMX_CHANNEL_LED-1]);
TIM2_SetCompare2(dmxData[DMX_CHANNEL_LED]);
TIM2_SetCompare3(dmxData[DMX_CHANNEL_LED+1]);
// TIM2_SetCompare3(128); //Test-data on pin PA3
}
};
}
static void CLK_Config(void)
{
/* Initialization of the clock */
/* Clock divider to HSI/1 */
CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
// reset clock
CLK_DeInit();
// Deactivate external and internal oscillator, activate internal oscillator
CLK_HSECmd(DISABLE);
CLK_LSICmd(DISABLE);
CLK_HSICmd(ENABLE);
// Wawait until oscillator is stable
while(CLK_GetFlagStatus(CLK_FLAG_HSIRDY) == FALSE);
// Clock Switching
CLK_ClockSwitchCmd(ENABLE);
CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV1);
// config for clock switching
CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSI,
DISABLE, CLK_CURRENTCLOCKSTATE_ENABLE);
// Deactivate clock for peripherals that are not required
CLK_PeripheralClockConfig(CLK_PERIPHERAL_SPI, DISABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_I2C, DISABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_ADC, DISABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_AWU, DISABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_UART1, ENABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER1, DISABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER2, ENABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER4, DISABLE);
}
void GPIO_setup(void)
{
GPIO_DeInit(GPIOA);
GPIO_Init(GPIOA, GPIO_PIN_3, GPIO_MODE_OUT_PP_HIGH_FAST);
GPIO_DeInit(GPIOD);
GPIO_Init(GPIOD, ((GPIO_Pin_TypeDef)GPIO_PIN_3 | GPIO_PIN_4),
GPIO_MODE_OUT_PP_HIGH_FAST);
}
// initialize timer 2 for PWM
void TIM2_setup(void)
{
TIM2_DeInit(); // reset timer 2
TIM2_TimeBaseInit(TIM2_PRESCALER_32, 255); // Timer 2 als Zeitbasis mit Vorteiler 32 und Periodenwert 1000 initialisieren
TIM2_OC1Init(TIM2_OCMODE_PWM1, TIM2_OUTPUTSTATE_ENABLE, 255, // set timer 2 channel 1 as pwm, activate output, pulse and polarity
TIM2_OCPOLARITY_HIGH);
TIM2_OC2Init(TIM2_OCMODE_PWM1, TIM2_OUTPUTSTATE_ENABLE, 255,// set timer 2 channel 2 as pwm, activate output, pulse and polarity
TIM2_OCPOLARITY_LOW);
TIM2_OC3Init(TIM2_OCMODE_PWM1, TIM2_OUTPUTSTATE_ENABLE, 255, // set timer 2 channel 3 as pwm, activate output, pulse and polarity
TIM2_OCPOLARITY_HIGH);
TIM2_Cmd(ENABLE); // activate timer 2
}
void UART_Config(void)
{
UART1_DeInit();
// Configure UART1 for DMX mode
UART1_Init(250000,
UART1_WORDLENGTH_8D,
UART1_STOPBITS_2, // 2 Stop-Bits für DMX
UART1_PARITY_NO,
UART1_SYNCMODE_CLOCK_DISABLE,
UART1_MODE_RX_ENABLE);
// Enable DMX receiver interrupt
UART1_ITConfig(UART1_IT_RXNE_OR, ENABLE);
// Enable global interrupts
enableInterrupts();
}
INTERRUPT_HANDLER(UART1_RX_IRQHandler, 18)
{
if (UART1_GetITStatus(UART1_IT_RXNE) != RESET)
{
uint8_t receivedData = UART1_ReceiveData8(); // receive data
if (dmxMessageStarted)
{
dataFree = false;
dmxData[dmxIndex] = receivedData; // write data in array
dmxIndex++;
if (dmxIndex >= DMX_CHANNEL_COUNT)
{
dmxIndex = 0;
dmxMessageStarted = false;
}
}
else
{
// break signal
if (receivedData == 0)
{
// digitalWrite(LED_BUILTIN, HIGH);
dataFree = true;
dmxMessageStarted = true; // begin of a new DMX message
dmxIndex = 0; // reset index
}
}
}
}
the project: I want to dim an RGB-LED with PWM (MCU: STM8S103). The amount of dimming should be received as a datastream over DMX which is implemented via serial. the problem: When I send data on a specific channel, the data is received, but there's a shift in the channel... So if I send data on channel 0 (DMXchannel 1), the channel which receives the data is drifting from 0 to 511, or even no data is received. So the system seem to be very unstable. Does someone know what could be the problem? here is my sktech: