Descrição breve
Ele registra principalmente algumas configurações e opções comumente usadas. Se forem encontrados erros, discuta-os na área de comentários.
Solução para o problema que o downloader não consegue baixar no projeto gerado pelo STM32CubeMX F1
Configuração de fonte de relógio RCC do Cubemx
Ao usar o cubo para configurar o relógio, existem duas opções:
- Fonte de relógio BYPASS (ignorar fonte de relógio)
refere-se aos componentes da unidade de relógio interno do chip que são necessários quando os cristais externos não são usados e os sinais de relógio são importados diretamente do mundo externo. É como se os componentes do drive dentro do chip fossem ignorados. - Ressonador Cristal / Cerâmico (oscilador de cristal externo)
Esta fonte de relógio é formada pela cooperação de um cristal externo passivo e o circuito de acionamento do relógio interno do MCU.Tem um certo tempo de inicialização e alta precisão.
Onde o HSE é um OSC_IN和OSC_OUT
cristal de contato esquemático de hardware
LSE é um diagrama esquemático de um OSC32_IN和OSC32_OUT
cristal de contato de hardware
Configure a árvore do relógio
A árvore do relógio deve se referir a se o hardware usa um relógio interno ou um oscilador de cristal externo, e então configurar a frequência desejada de acordo com o manual de dados do chip ou manual de referência, e não pode exceder a frequência máxima exigida no manual.
A imagem acima mostra a árvore do relógio da versão C oficial do Robomaster da rotina
Pinos GPIO de configuração do Cubemx
-
Nível de saída GPIO: nível de saída padrão
-
Modo GPIO:
saída push pull open dreno
Ootput open dreno push-pull para
entender o dreno aberto e saída push-pull -
GPIO Pull-up / Pull-down: resistência pull-up e pull-up, deve ser configurado de acordo com o hardware.
-
Velocidade máxima de saída:
GPIO_SPEED_LOW; (2) 2MHz
GPIO_SPEED_MEDIUM; (25) 12,5 MHz ~ 50
MHz GPIO_SPEED_FAST; (50) 25MHz ~ 100 MHz
GPIO_SPEED_HIGH; (100) 50 MHz ~ 200 MHz
Configuração da porta serial UART
- Modo:
comunicação assíncrona assíncrona Comunicação
síncrona síncrona
Geralmente não é usado em outros modos
Interrupção da porta serial UART
Precisa redefinir a função de retorno de chamada de interrupção
Modo DMA da porta serial UART
-
Modo:
Normal: Modo normal, você precisa habilitar continuamente o envio e recebimento.
Circular: Modo circular -
Largura de dados: dados transmitidos por DMA de uma só vez
-
Endereço de incremento: se o endereço aumenta após o DMA transferir dados de largura de dados
Definição de macro de ativação de DMA de porta serial :
__HAL_DMA_ENABLE, __HAL_DMA_ENABLE_IT.
Função de retorno de chamada de interrupção de DMA da porta serial :
O
transceptor da porta serial pode usar a função DMA ao mesmo tempo. No entanto, dois canais DMA diferentes são necessários. Há uma relação correspondente entre a porta serial e o canal DMA. Consulte o manual de referência.
Canal
DMA O DMA tem vários canais. Embora cada canal possa receber solicitações de vários periféricos, ele só pode receber um ao mesmo tempo, não vários ao mesmo tempo.
Cubemx configura o DMA para habilitar automaticamente a interrupção global do DMA, mas é melhor habilitá-lo novamente com _HAL_DMA_ENABLE_IT.
Se você aceitar o mesmo comprimento de dados todas as vezes no modo de loop, poderá definir o registro DMA_SxNDTR. Por segurança, você também pode redefini-lo todas as vezes. Ele pode ser usado para verificar manualmente se há um erro de comprimento de dados em um quadro de transmissão de dados. Lembre-se de desativar o DMA antes de configurar
Recepção ociosa da porta serial + buffer duplo DMA
- Depois que a porta serial recebe um quadro de dados (um quadro de dados consiste em vários bytes, defina a quantidade de dados a receber por vez), o
IDLE
bit será definido como 1. - O buffer duplo mudará a área de armazenamento de destino após receber um quadro de dados (no final da transferência DMA). Dessa forma, se o quadro anterior de dados estiver sendo processado, o novo quadro de dados não será sobrescrito neste momento.
- Os dados aqui são todos dados de comprimento fixo.
- O modo MTM (memória para memória) do DMA não oferece suporte a buffers duplos. O buffer duplo deve ser definido para o modo cíclico.
-
Configurar buffer duplo
Método 1:
Use a função de biblioteca HALHAL_DMAEx_MultiBufferStart_IT()
e, a seguir, julgue o buffer atual na função de interrupção. (Alguns chips podem não suportar esta função de biblioteca HAL, como f103). Ainda preciso habilitar o DMA.Método 2:
Registre o modo de buffer duplo e, em seguida, julgue o buffer atual na função de interrupção. Tome USART3 como exemplo, lembre-se de modificar o fluxo DMA e o registro uart.//enable the DMA transfer for the receiver request //使能DMA串口接收 SET_BIT(huart3.Instance->CR3, USART_CR3_DMAR); //enalbe idle interrupt //使能空闲中断 __HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE); //disable DMA //失效DMA __HAL_DMA_DISABLE(&hdma_usart3_rx); while(hdma_usart3_rx.Instance->CR & DMA_SxCR_EN) { __HAL_DMA_DISABLE(&hdma_usart3_rx); } //外设寄存器 hdma_usart3_rx.Instance->PAR = (uint32_t) & (USART3->DR); //memory buffer 1 //内存缓冲区1 hdma_usart3_rx.Instance->M0AR = (uint32_t)(rx1_buf); //memory buffer 2 //内存缓冲区2 hdma_usart3_rx.Instance->M1AR = (uint32_t)(rx2_buf); //data length //一帧的数据长度 hdma_usart3_rx.Instance->NDTR = dma_buf_num; //enable double memory buffer //使能双缓冲区 SET_BIT(hdma_usart3_rx.Instance->CR, DMA_SxCR_DBM); //enable DMA //使能DMA __HAL_DMA_ENABLE(&hdma_usart3_rx);
Os dois métodos acima podem ser adicionados a
HAL_UART_MspInit()中的用户代码处
-
CT
Bit de julgamento na interrupção da porta serial
Primeiro julgue se a área de buffer atual é Memory0 ou Memory1, se for 0, os dados em 1 serão processados; se for 1, a informação em 0 será processada, e o processamento não afetam a recepção de dados em outro buffer:
//串口中断
void USART3_IRQHandler(void)
{
if(huart3.Instance->SR & UART_FLAG_RXNE)//接收到数据
{
__HAL_UART_CLEAR_PEFLAG(&huart3);//清除校验错误中断位,如果使能对应中断会进入
}
else if(USART3->SR & UART_FLAG_IDLE)//检测到总线空闲
{
static uint16_t this_time_rx_len = 0;
__HAL_UART_CLEAR_PEFLAG(&huart3);//清除校验错误中断位,如果使能对应中断会进入
if ((hdma_usart3_rx.Instance->CR & DMA_SxCR_CT) == RESET)//DMA_SxCR寄存器的CT位为0,处理缓冲区1数据
{
/* Current memory buffer used is Memory 0 */
//disable DMA
//失效DMA
__HAL_DMA_DISABLE(&hdma_usart3_rx);
//get receive data length, length = set_data_length - remain_length
//获取接收数据长度,长度 = 设定长度 - 剩余长度
this_time_rx_len = SBUS_RX_BUF_NUM - hdma_usart3_rx.Instance->NDTR;
//reset set_data_lenght
//重新设定数据长度
hdma_usart3_rx.Instance->NDTR = SBUS_RX_BUF_NUM;
//set memory buffer 1
//设定缓冲区1
hdma_usart3_rx.Instance->CR |= DMA_SxCR_CT;
//enable DMA
//使能DMA
__HAL_DMA_ENABLE(&hdma_usart3_rx);
if(this_time_rx_len == RC_FRAME_LENGTH)
{
sbus_to_rc(sbus_rx_buf[1], &rc_ctrl);
}
}
else //当前缓冲区为1,处理缓冲区,0数据
{
/* Current memory buffer used is Memory 1 */
//disable DMA
//失效DMA
__HAL_DMA_DISABLE(&hdma_usart3_rx);
//get receive data length, length = set_data_length - remain_length
//获取接收数据长度,长度 = 设定长度 - 剩余长度
this_time_rx_len = SBUS_RX_BUF_NUM - hdma_usart3_rx.Instance->NDTR;
//reset set_data_lenght
//重新设定数据长度
hdma_usart3_rx.Instance->NDTR = SBUS_RX_BUF_NUM;
//set memory buffer 0
//设定缓冲区0
hdma_usart1_rx.Instance->CR &= ~(DMA_SxCR_CT);
// 或者改为 DMA1_Stream1->CR &= ~(DMA_SxCR_CT);
//如果不是usart3,记得修改DMA流
//enable DMA
//使能DMA
__HAL_DMA_ENABLE(&hdma_usart3_rx);
if(this_time_rx_len == RC_FRAME_LENGTH)
{
//处理遥控器数据
sbus_to_rc(sbus_rx_buf[0], &rc_ctrl);
}
}
}
}
A interrupção inativa é usada aqui, e a interrupção inativa precisa ser habilitada com antecedência.
Você pode consultar o buffer duplo da biblioteca HAL
Após o teste, o uso da Eu estava errado antes. Habilitar o bit de buffer duplo irá de fato trocar automaticamente o buffer. Como a rotina de controle remoto da placa C é um pouco problemática, o julgamento está errado.HAL_DMAEx_MultiBufferStart_IT()
função ainda precisa substituir o buffer na interrupção.
IIC
Half-duplex
Funções de biblioteca HAL comumente usadas:
HAL_I2C_Mem_Read () e HAL_I2C_Mem_Write (), etc., consulte a documentação de ajuda da biblioteca HAL
SPI
Funções de biblioteca HAL full-duplex comumente usadas:
HAL_SPI_Transmit ()
O IIC e o SPI são usados principalmente para comunicação com uma pequena quantidade de dados, e a condução real de diferentes periféricos pode exigir embalagem adicional.
POSSO
TIM
- Modo mestre-escravo, raramente usado
-
Relógio interno: relógio interno, ou seja, fonte de relógio
-
Entrada de disparo externo ETR2 (ETR) (aplicável apenas a TIM2, 3, 4)
-
PSC: Prescaler, a fonte do relógio é o relógio do temporizador através deste prescaler. A frequência do relógio do temporizador é igual à frequência da fonte do relógio / (psc + 1)
-
Modo do contador: para cima, para baixo e três contagens alinhadas ao centro. O cronômetro básico só pode fazer uma contagem progressiva.
-
ARR: valor de recarga automática, período do temporizador T = (ARR + 1) * (1 / frequência do relógio do temporizador) = (ARR + 1) * (PSC + 1) / 72M
-
Divisão do relógio interno: O fator de divisão do relógio, necessário para configurar o tempo morto.
-
auto-reload-preload: auto-reload) enable
-
Saída de acionamento dos parâmetros TRGO (TRGO)
Para fazer o cronômetro funcionar, chame a função de biblioteca HAL_TIM_Base_Start ().
Para usar a interrupção do cronômetro, chame a função de biblioteca HAL_TIM_Base_Start_IT ().
Ambos PSC e ARR devem primeiro ser decrementados em 1, porque de acordo com o manual de referência, o valor do registro é o valor definido mais 1
TIM_PWM
- Pulso: Defina o ciclo de serviço e defina o valor do registro CCR. Ciclo de trabalho P = CCR / (ARR + 1)
TIM_ENCODER
Apenas TIM1 e TIM2 têm modo de codificador
- Modo do codificador: T1 e T2 // O codificador captura na borda ascendente de TI1 TI2, a borda ascendente de TI1 adiciona e subtrai o contador de acordo com o nível de TI2 e a borda ascendente de TI2 adiciona e subtrai o contador de acordo com o nível de TI1.
Polaridade: Aumento
// O parâmetro TIM_EncoderMode é o modo, contagem monofásica (pode apenas refletir a velocidade) ou contagem bifásica (velocidade e direção)
// TI1 e TI2 são ambos contados na borda, e se é para cima ou para baixo depende da rotação para a frente ou reversa
// A captura ocorre na borda de subida IC1 e IC2
Consulte o manual para o modo de codificador
ADC / DAC
- ADC_mode: Use apenas um ADC para configurar como modo independente e use vários ADCs (ADC1 / 2/3) para configurar como
- Alinhamento de dados: alinhamento de dados à esquerda / direita
- Modo de conversão de varredura: modo de varredura, a ser ativado ao usar vários canais
- Modo de conversão contínua: conversão contínua / conversão única, quando configurada como uma conversão única, os dados serão convertidos apenas uma vez e irá parar, e será acionado novamente
- Ativar conversões regulares: conversão regular,
- Habilitar conversões injetadas: conversões injetadas
Habilite ADC antes de começar:
HAL_ADC_Start ou HAL_ADC_Start_IT