2022-11-28 10:23 AM
I have spent a few weeks reviewing HAL related and LL related neopixel libs however I would love if there was someone who had a working version of literally just the ability to set up a neopixel on any port and simply light it or light a few neopixels in an array.
I have found several with HALs but it really does not give a good understanding of how this is done from scratch.
To be clear I am not looking for a HAL solution. I am looking for a bare-metal no library solution.
Thank you in advance.
2022-11-29 01:59 AM
The first snippet was for SPI, the second is for timer PWM output - it's written in the text. Some convenient #defines from my own header files are used in the code to make it easier to read - they are quite easy to guess.
2022-11-29 02:44 AM
#define WSDMA DMA1
#define WSDMACH DMA1_Channel1
#define DMA_IFCR_CGIF_WS DMA_IFCR_CGIF1
#define WSTIM_CCR TIM1->CCR1
DMA_IFCR_CGIF1 I assume this is SPI1?
TIM1->CCR1 I assume this is PWM?
2022-11-29 02:48 AM
#define WSDMA DMA1
#define WSDMACH DMA1_Channel1
#define DMA_IFCR_CGIF_WS DMA_IFCR_CGIF1
#define WSTIM_CCR TIM1->CCR1
I assume DMA_Channel1 is SPI1? I do not see where you are selecting a specific SPI and PWM output.
It is not obvious what pin you are using as I know in the datasheet I have to see where SPI1 can be mapped to but I do not see it here.
2022-11-29 11:29 AM
Nevermind I got it to work. Just took some time. Thank you!
2023-12-22 02:15 PM
I know this is an old thread, but I'm struggling to get anything to work on a STM32G030J6M6, I want to drive a number of smd ws2812. Is there maybe any code you could share if you got it working? Or maybe could you share the many HAL examples that you mentioned?
Thanks!!
2023-12-23 03:50 PM - edited 2023-12-24 06:15 AM
This is my code for G030 using UART with 7-bit frames, MSB first, used in my Christmas star.
int main(void)
{
RCC->PLLCFGR = RCC_PLLCFGR_PLLMV(1) | RCC_PLLCFGR_PLLNV(9) | RCC_PLLCFGR_PLLRV(3)
| RCC_PLLCFGR_PLLREN | RCC_PLLCFGR_PLLSRC_HSI; //
RCC->CR |= RCC_CR_PLLON; // turn PLL on
while (!(RCC->CR & RCC_CR_PLLRDY)); // wait for PLL lock
FLASH->ACR |= FLASH_ACR_PRFTEN | 1; // enable prefetch, 1 wait state
RCC->CFGR |= RCC_CFGR_SW_PLLRCLK; // switch to PLL clock
RCC->IOPENR |= RCC_IOPENR_GPIOAEN | RCC_IOPENR_GPIOBEN;
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
RCC->APBENR2 = RCC_APBENR2_USART1EN;
// the UART may also work with 8-bit frames, this requires shifting the data by one to the left (verified)
WS_UART->BRR = (HCLK_FREQ + WSBAUD / 2) / WSBAUD;
WS_UART->CR2 = USART_CR2_TXINV | USART_CR2_MSBFIRST | USART_CR2_DATAINV | USART_CR2_SWAP;
WS_UART->CR3 = USART_CR3_DMAT;
WS_UART->CR1 = USART_CR1_M1 | USART_CR1_TE | USART_CR1_UE;
WS_DMACH->CPAR = (uint32_t)&WS_UART->TDR;
GPIOB->MODER = BF2(7, GPIO_MODER_AF); // USART1
DMAMUX1_Channel0->CCR = DMAREQ_ID_USART1_TX;
SysTick_Config(HCLK_FREQ / SYSTICK_FREQ);
for (;;)
__WFI();
}
struct rgb_ {
uint8_t r, g, b;
};
struct rgb_ lc[NLEDS];
static uint8_t txbuf[NLEDS * 8];
void encode(uint8_t *encbuf, const struct rgb_ *img, uint16_t nleds)
{
// MSB-first encoding table
static const uint8_t uenc[] = {
0000 | 022, 0001 | 022, 0010 | 022, 0011 | 022,
0100 | 022, 0101 | 022, 0110 | 022, 0111 | 022
};
for (uint16_t i = 0; i < nleds; i++)
{
uint32_t v = img[i].r | img[i].g << 8 | img[i].b << 16;
for (uint8_t b = 0; b < 8; b++)
{
*encbuf++ = uenc[v >> 21 & 7];
v <<= 3;
}
}
}
void ws_start(void)
{
encode(txbuf, lc, NLEDS);
WS_DMACH->CCR = 0;
WS_DMACH->CMAR = (uint32_t)txbuf;
WS_DMACH->CNDTR = sizeof(txbuf);
WS_DMACH->CCR = DMA_CCR_DIR_M2P | DMA_CCR_MINC | DMA_CCR_EN;
}