demo of driving MAX2719 dot matrix displays with STM32F103 Bluepill
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
f103-dotmatrix/project/hw_init.c

250 lines
5.8 KiB

#include "hw_init.h"
#include "com/iface_usart.h"
#include "com/com_fileio.h"
#include "com/datalink.h"
#include "utils/debounce.h"
#include "utils/timebase.h"
#include "bus/event_queue.h"
#include "com/debug.h"
// ---- Private prototypes --------
static void conf_gpio(void);
static void conf_usart(void);
static void conf_spi(void);
static void conf_systick(void);
static void conf_subsystems(void);
static void conf_irq_prios(void);
static void conf_adc(void);
// ---- Public functions ----------
/**
* @brief Initialize hardware resources
*/
void hw_init(void)
{
conf_gpio();
conf_usart();
conf_systick();
conf_spi();
conf_adc();
conf_irq_prios();
conf_subsystems();
}
// ---- Private functions ---------
static void conf_irq_prios(void)
{
NVIC_SetPriorityGrouping(0); // 0 bits for sub-priority
// SysTick - highest prio, used for timeouts
NVIC_SetPriority(SysTick_IRQn, 0); // SysTick - for timeouts
NVIC_SetPriority(USART2_IRQn, 6); // USART - datalink
NVIC_SetPriority(USART1_IRQn, 10); // USART - debug
// FIXME check , probably bad ports
}
/**
* @brief Configure SW subsystems
*/
static void conf_subsystems(void)
{
// task scheduler subsystem
timebase_init(15, 15);
// event and task queues
queues_init(30, 30);
// initialize SBMP for ESP8266
dlnk_init();
}
/**
* @brief Configure GPIOs
*/
static void conf_gpio(void)
{
GPIO_InitTypeDef gpio_cnf;
GPIO_StructInit(&gpio_cnf);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
// Red LED
gpio_cnf.GPIO_Pin = GPIO_Pin_13;
gpio_cnf.GPIO_Mode = GPIO_Mode_Out_PP;
gpio_cnf.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOC, &gpio_cnf);
// UARTs
gpio_cnf.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_9;
gpio_cnf.GPIO_Mode = GPIO_Mode_AF_PP;
gpio_cnf.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOA, &gpio_cnf);
gpio_cnf.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_3;
gpio_cnf.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &gpio_cnf);
// A0 - analog input for ADC
gpio_cnf.GPIO_Pin = GPIO_Pin_0;
gpio_cnf.GPIO_Mode = GPIO_Mode_AIN;
gpio_cnf.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOA, &gpio_cnf);
// SPI
gpio_cnf.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7;
gpio_cnf.GPIO_Mode = GPIO_Mode_AF_PP;
gpio_cnf.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOA, &gpio_cnf);
// SPI NSS out
gpio_cnf.GPIO_Pin = GPIO_Pin_4;
gpio_cnf.GPIO_Mode = GPIO_Mode_Out_PP;
gpio_cnf.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOA, &gpio_cnf);
}
/**
* @brief Configure USARTs
*/
static void conf_usart(void)
{
// Debug interface, working as stdout/stderr.
debug_iface = usart_iface_init(USART2, 115200, 256, 256);
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
debug_iface->file = stdout;
// Datalink iface
data_iface = usart_iface_init(USART1, 460800, 256, 256);
}
/**
* @brief Configure SPI
*/
static void conf_spi(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2ENR_SPI1EN, ENABLE);
SPI_InitTypeDef spi_cnf;
SPI_StructInit(&spi_cnf);
spi_cnf.SPI_Direction = SPI_Direction_1Line_Tx;
spi_cnf.SPI_Mode = SPI_Mode_Master;
spi_cnf.SPI_NSS = SPI_NSS_Soft;
spi_cnf.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
SPI_Init(SPI1, &spi_cnf);
SPI_Cmd(SPI1, ENABLE);
}
/**
* @brief Configure 1 kHz SysTick w/ interrupt
*/
static void conf_systick(void)
{
SysTick_Config(F_CPU / 1000);
}
static void conf_adc(void)
{
RCC_ADCCLKConfig(RCC_PCLK2_Div4);
RCC_APB2PeriphClockCmd(RCC_APB2ENR_ADC1EN, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1ENR_TIM3EN, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBENR_DMA1EN, ENABLE);
NVIC_EnableIRQ(DMA1_Channel1_IRQn);
// Configure the ADC
ADC_DeInit(ADC1);
ADC_InitTypeDef adc_cnf;
adc_cnf.ADC_Mode = ADC_Mode_Independent;
adc_cnf.ADC_ScanConvMode = DISABLE;
adc_cnf.ADC_ContinuousConvMode = DISABLE;
adc_cnf.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T3_TRGO;
adc_cnf.ADC_DataAlign = ADC_DataAlign_Right;
adc_cnf.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &adc_cnf);
ADC_Cmd(ADC1, ENABLE);
ADC_ExternalTrigConvCmd(ADC1, ENABLE);
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_7Cycles5);
// calib
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
// Configure the DMA timer
TIM_DeInit(TIM3);
TIM_TimeBaseInitTypeDef tim_cnf;
tim_cnf.TIM_Period = 1800;
tim_cnf.TIM_Prescaler = 1;
tim_cnf.TIM_ClockDivision = TIM_CKD_DIV1;
tim_cnf.TIM_CounterMode = TIM_CounterMode_Up;
tim_cnf.TIM_RepetitionCounter = 0x0000;
TIM_TimeBaseInit(TIM3, &tim_cnf);
TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_Update);
//TIM3->CR1 |= TIM_CR1_URS; // generate update on overflow
//TIM3->CR2 |= TIM_CR2_MMS_1; // trig on update
}
void start_adc_dma(uint32_t *memory, uint32_t count)
{
ADC_Cmd(ADC1, DISABLE);
DMA_DeInit(DMA1_Channel1);
DMA_InitTypeDef dma_cnf;
dma_cnf.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
dma_cnf.DMA_MemoryBaseAddr = (uint32_t)memory;
dma_cnf.DMA_DIR = DMA_DIR_PeripheralSRC;
dma_cnf.DMA_BufferSize = count;
dma_cnf.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
dma_cnf.DMA_MemoryInc = DMA_MemoryInc_Enable;
dma_cnf.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
dma_cnf.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
dma_cnf.DMA_Mode = DMA_Mode_Normal;
dma_cnf.DMA_Priority = DMA_Priority_Low;
dma_cnf.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &dma_cnf);
DMA_ITConfig(DMA1_Channel1, DMA1_IT_TC1, ENABLE);
ADC_Cmd(ADC1, ENABLE);
ADC_DMACmd(ADC1, ENABLE);
DMA_Cmd(DMA1_Channel1, ENABLE);
TIM_Cmd(TIM3, ENABLE);
}
void DMA1_Channel1_IRQHandler(void)
{
DMA_ClearITPendingBit(DMA1_IT_TC1);
DMA_ClearITPendingBit(DMA1_IT_TE1);
DMA_DeInit(DMA1_Channel1);
TIM_Cmd(TIM3, DISABLE);
ADC_DMACmd(ADC1, DISABLE);
tq_post(audio_capture_done, NULL);
}