Registro de interpretação de código aberto código-fonte interno sys.c

#include "./SYSTEM/sys/sys.h"

void sys_nvic_set_vector_table(uint32_t baseaddr, uint32_t offset) // (definir tabela de vetores de interrupção)

{

    // O registro VTOR do processador Cortex-M se preocupa apenas com os 0~8 bits do endereço, e os valores dos 9~31 bits (23 bits maiores) são ignorados

    // A operação AND bit a bit reserva os bits binários de 0 a 8 do endereço de deslocamento,

    // Desta forma, o deslocamento do endereço da posição inicial da tabela de vetores de interrupção pode ser definido para o registrador VTOR, completando assim a operação de deslocamento da tabela de vetores de interrupção.

    SCB->VTOR = endereço base | (deslocamento & (uint32_t)0xFFFFFE00);

    // Método de implementação: operação AND bit a bit entre o deslocamento do endereço de deslocamento da tabela de vetor de interrupção especificada e os 9 bits mais baixos (ou seja, os 0 ~ 8 bits do endereço de deslocamento),

    // Em seguida, execute uma operação OR bit a bit com a variável baseaddr e atribua o resultado ao registro VTOR.

}

static void sys_nvic_priority_group_config(uint8_t group) // (--função local-- configurar agrupamento de prioridade de interrupção NVIC,)

{

    /*--Conhecimento complementar--

    NVIC_PRIORITYGROUP_4 é um esquema baseado em controlador de interrupção (NVIC) para implementar agrupamento de prioridades.

    É um método de agrupamento baseado na prioridade de hardware no processador Cortex-M.

    Em NVIC_PRIORITYGROUP_4, existem 4 grupos de prioridade, de 0 a 3 (prioridade de alta para baixa).

    Dentro de cada grupo prioritário, existem 16 níveis de prioridade. Entre elas, a prioridade 0 é o nível mais alto e a prioridade 15 é o nível mais baixo.

    Dentro do mesmo grupo de prioridades, diferentes subprioridades podem ser definidas para cada interrupção

    Tanto a prioridade de preempção quanto a prioridade de resposta recebem 16 níveis. A prioridade de preempção é usada para preempção entre interrupções e a prioridade de resposta é usada para controle de prioridade dentro da função de serviço de interrupção.

    Tabela de vetores de interrupção ----------> manual de referência p130 tabela de páginas 54

    */

    uint32_t temp, temp1;

    temp1 = (~group) & 0x07; // realiza inversão bit a bit (~) no grupo de variáveis ​​e operação AND bit a bit com número binário 0x07

    temp1 <<= 8; // desloca temp1 para a esquerda em 8 bits. O objetivo é colocar o valor do grupo de prioridade entre os 15º e 13º bits do AIRCR.

    temp = SCB->AIRCR; // Lê o valor do AIRCR (registro de controle de interrupção e redefinição da aplicação) no registro do bloco de controle do sistema (SCB) para temp

    temp &= 0X0000F8FF; // operação AND bit a bit entre temp e 0x0000F8FF, o objetivo é definir o (grupo de prioridade de interrupção) e (subprioridade) do AIRCR como 0 para reconfiguração

    temp |= 0X05FA0000; // Opera o valor de temp com 0x05FA0000 bit a bit, o número significa usar o esquema NVIC_PRIORITYGROUP_4 para codificação de prioridade. Neste cenário, o agrupamento prioritário é 0b10

    temp |= temp1; // Executa uma operação OR bit a bit em temp1 e temp e coloca o valor agrupado no bit correspondente. Finalmente, os primeiros três bits são definidos como valor de agrupamento de prioridade.

    SCB->AIRCR = temp; // Escreve temp em (AIRCR) no registrador (SCB), completando assim todo o processo de configuração do agrupamento de prioridade de interrupção NVCI.

}

void sys_nvic_init(uint8_t pprio, uint8_t sprio, uint8_t ch, uint8_t group) // (inicialização do controlador de interrupção NVIC)

{

    sys_nvic_priority_group_config(group); // Chame a função sys_nvic_priority_group_config, o parâmetro é group, para completar a configuração do agrupamento de prioridade de interrupção NVCI

    temperatura uint32_t;

    temp = pprio << (4 - group); // Desloca o valor de pprio para a esquerda (4-group) e armazena o resultado em temp. O objetivo é calcular a prioridade mestre

    temp |= sprio & (0x0f >> group); // Armazene os 4 bits inferiores do sprio em temp, use 0x0f para deslocar os bits para a direita (agrupar) e execute a operação AND bit a bit e mantenha os 4 bits inferiores em temp. O objetivo é calcular a partir da prioridade

    temp &= 0xf; // Opera temp e 0xf bit a bit e (&) para garantir que o valor em temp não seja maior que 15.

    NVIC->ISER[ch / 32] |= 1 << (ch % 32); // Define a posição da linha de interrupção correspondente no registro NVIC->ISER[ch/32] como 1 e habilita a interrupção correspondente Arame;

    NVIC->IP[ch] |= temp << 4; // Desloca a temperatura de prioridade calculada em 4 bits para a esquerda e escreve-a no registro NVIC->IP[ch] para especificar a prioridade da interrupção correspondente.

}

void sys_nvic_ex_config(GPIO_TypeDef *p_gpiox, uint16_t pinx, uint8_t tmode) //(configuração de interrupção externa NVIC)

{

    deslocamento uint8_t;

    uint32_t gpio_num = 0;

    uint32_t pinos = 0, curpin = 0, pos = 0;

    /*Descrição do parâmetro

    offset é usado para armazenar o deslocamento de bit do número do pino no registro EXTICR.

    gpio_num armazena o número GPIO correspondente,

    pinpos e curpin são usados ​​para percorrer e verificar cada bit no número do pino, respectivamente,

    pos é usado para gerar a máscara de bits,

    */

    gpio_num = ((uint32_t)p_gpiox - (uint32_t)GPIOA) / 0X400; // Calcule a diferença entre o endereço da porta GPIO GPIOA no barramento AHB e o endereço do parâmetro de entrada p_gpiox e depois divida por 0x400 para obter o número GPIO correspondente.

    RCC->APB2ENR |= 1 << 0; // Habilita o clock AFIO, configura o bit do clock AFIO no registrador RCC->APB2ENR para acessar o registrador AFIO

    for (pinpos = 0; pinpos < 16; pinpos++) // percorre cada bit no número do pino

    {

        pos = 1 << pinpos; // use pos para gerar uma máscara de bits,

        curpin = pinx & pos; // Use a operação bit a bit AND (&) para obter o bit atual do número do pino

        if (curpin == pos) // Se o bit atual for 1, significa que o pino precisa ser configurado com a função EXTI.

        {

            offset = (pinpos % 4) * 4; // Calcula seu deslocamento de bit correspondente no registro EXTICR,

            AFIO->EXTICR[pinpos / 4] &= ~(0x000F << offset); // Em seguida, limpa o valor na posição especificada no registro AFIO->EXTICR[pinpos / 4]

            AFIO->EXTICR[pinpos / 4] |= gpio_num << offset; // Em seguida, armazene gpio_num nesta posição de acordo com o valor de deslocamento de bit do deslocamento de deslocamento

            EXTI->IMR |= 1 << pinpos; // Defina a posição do pino correspondente no registro EXTI->IMR como 1 e habilite a interrupção EXTI correspondente ao pino (ou seja, a interrupção BITx da linha pode ser habilitada ).

            /*Além disso, configure o modo de disparo da linha EXTI correspondente de acordo com o modo de disparo de entrada tmode*/

            if (tmode & 0x01)

                EXTI->FTSR |= 1 << pinpos; // Se o bit mais baixo do tmode for 1, habilita o trigger de borda descendente;

            if (tmode & 0x02)

                EXTI->RTSR |= 1 << pinpos; // Se o segundo bit baixo do tmode for 1, habilite o disparo da borda ascendente.

        }

    }

}

void sys_gpio_remap_set(uint8_t pos, uint8_t bit, uint8_t val) //(remapeamento de pinos GPIO)

{

    uint32_t temp = 0; // temp é usado para salvar a máscara de bits gerada e i é usado para percorrer os bits que precisam ser configurados.

    uint8_t i = 0;

    RCC->APB2ENR |= 1 << 0; // Habilita o relógio AFIO, temp é usado para salvar a máscara de bits gerada e i é usado para percorrer os bits que precisam ser configurados.

    for (i = 0; i < bit; i++) // Calcula a temperatura da máscara de bits que precisa ser configurada de acordo com o parâmetro bit passado

    {

        temp <<= 1; // O parâmetro bit indica quantos bits precisam ser configurados, portanto é necessário gerar uma máscara cujos bits inferiores sejam todos 1,

        temp += 1; // Gerado usando temp bitwise left shift e operação bit a bit OR.

    }

    AFIO->MAPR &= ~(temp << pos); // Limpa a posição a ser configurada no registro AFIO->MAPR. Isso pode ser feito deslocando o bit pos para a esquerda de temp e depois invertendo (~) e, em seguida, tomando o valor original implementação da operação bit a bit AND (&)

    AFIO->MAPR |= (uint32_t)val << pos; // Por fim, defina os bits a serem configurados para novos valores no registro AFIO->MAPR. Você pode mover o novo valor para a esquerda por bits pos e então pressionar ou (|) para o valor original para completar a configuração.

}

//(configuração do pino GPIO)

//Definição da estrutura:

// estrutura typedef

// {

// volátil uint32_t MODER; // registro do modo de porta GPIO

// volátil uint16_t OTYPER; // registro do tipo de saída da porta GPIO

// uint16_t RESERVED0; // Reservado, o valor é 0x02

// volátil uint32_t OSPEEDR; // registro de velocidade de saída da porta GPIO

// volátil uint32_t PUPDR; // registro pull-up/pull-down da porta GPIO

// volátil uint16_t IDR; // registro de dados de entrada da porta GPIO

// uint16_t RESERVED1; // Reservado, o valor é 0x0A

// volátil uint16_t ODR; // registro de dados de saída da porta GPIO

// uint16_t RESERVED2; // Reservado, o valor é 0x0E

// volátil uint16_t BSRR; // conjunto/redefinição de registro de bits da porta GPIO

// uint16_t RESERVED3; // Reservado, o valor é 0x12

// volátil uint16_t LCKR; // registro de bloqueio de configuração da porta GPIO

// uint16_t RESERVED4; // Reservado, o valor é 0x16

// volátil uint16_t AFR[2]; // registro de função alternativa da porta GPIO

// uint16_t RESERVED5[10]; // Reservado, o valor é 0x1C-0x28

// volátil uint32_t BRR; // registrador de redefinição de bit GPIO

// } GPIO_TypeDef;

void sys_gpio_set(GPIO_TypeDef *p_gpiox, uint16_t pinx, modo uint32_t, uint32_t otype, uint32_t ospeed, uint32_t pupd)

{

    /*introdução de parâmetros

    p_gpiox aponta para o endereço de registro do GPIOx (x é A, B, C, etc.),

    pinx representa o pino a ser configurado (pode ser múltiplo, representado por bits binários)

    , mode indica o modo de funcionamento do pino (entrada, saída, multiplexação, etc.),

    otype indica o tipo de saída (dreno aberto ou push-pull),

    ospeed indica a taxa de saída,

    pupd significa modo pull-up e pull-down. */

    uint32_t pinos = 0, pos = 0, curpin = 0;

    // pinpos é usado para verificar ciclicamente cada pino da porta GPIO, pos é usado para verificar se o pino precisa ser configurado e curpin é o resultado da verificação.

    configuração uint32_t = 0;

    // variável de configuração, o valor inicial é 0, usado para salvar uma determinada configuração de IO

    for (pinpos = 0; pinpos < 16; pinpos++) // Use o loop for para processar os pinos com pinpos 0~15 por vez.

    {

        pos = 1 << pinpos; // Desloca 1 para a esquerda de pinpos e atribui-o a pos, ou seja, pos é usado para verificar se o pino correspondente precisa ser configurado

        curpin = pinx & pos; // As informações de configuração do pino são armazenadas no pinx, use a operação de bit & para obter curpin, ou seja, se o pino precisa ser configurado.

        if (curpin == pos) // Se curpin for igual a pos, significa que o pino precisa ser configurado.

        {

            config = 0; // Se a configuração for necessária, primeiro limpe config para indicar que o pino está configurado como modo de entrada analógica padrão.

            if ((mode == 0X01) || (mode == 0X02)) // se o modo for modo de saída normal ou modo de função alternativa

            {

                config = ospeed & 0X03; // OU os 2 bits inferiores do parâmetro de velocidade ospeed com os 2 bits inferiores da configuração para obter bit0/1, indicando a configuração de MODE[1:0].

                config |= (otype & 0X01) << 2; // OU o bit inferior do otype com o segundo bit da configuração para obter a configuração de CNF[0].

                config |= (mode - 1) << 3; // Desloca o valor de mode menos 1 para a esquerda em 3 bits e então OR com o terceiro bit de config para obter a configuração de CNF[1].

            }

            else if (mode == 0) // Se o modo for igual a 0, é o modo de entrada normal.

            {

                if (pupd == 0) // Se não houver pull-up e pull-down, significa modo de entrada flutuante.

                {

                    config = 1 << 2; // Define o segundo e terceiro bits da configuração para 0 1, o que significa modo de entrada flutuante.

                }

                else // Caso contrário (isto é, com modos de entrada pull-up e pull-down).

                {

                    config = 1 << 3; // Define o segundo e terceiro bits da configuração como 1 0, indicando o modo de entrada para cima e para baixo

                    /*O seguinte é puxar para cima ou para baixo o pino da porta GPIO de acordo com o bit baixo do parâmetro pupd. */

                    p_gpiox->ODR &= ~(1 << pinpos); // Limpa o bit do pino correspondente do ODR,

                    p_gpiox->ODR |= (pupd & 0X01) << pinpos; // Então, de acordo com o bit inferior do pupd, mova o bit do pino correspondente para a esquerda, execute a operação OR e defina-o como pull-up ou pull-down .

                }

            }

            /*O seguinte julga o registro CRH ou CRL onde o pin está localizado de acordo com os pinpos. */

            if (pinpos <= 7) // Se o pino pinpos atualmente processado estiver nos 8 bits inferiores, o registro correspondente é o registro CRL.

            {

                p_gpiox->CRL &= ~(0X0F << (pinpos * 4)); // Primeiro desloca os pinos para a esquerda em 2 bits (equivalente a multiplicar por 4) para obter o deslocamento (8 bits inferiores), depois desloca 0X0F para a esquerda pouco de mudança,

                                                         // Obtém a máscara a ser escrita no registrador e então usa o código inverso para limpar o bit especificado pela máscara

                p_gpiox->CRL |= config << (pinpos * 4); // Desloca a configuração para a esquerda pelo bit de deslocamento e escreve o resultado no registrador CRL.

            }

            else // Se a posição do pino pinpos atualmente processado estiver nos 8 bits superiores, o registro correspondente é o registro CRH.

            {

                p_gpiox->CRH &= ~(0X0F << ((pinpos - 8) * 4)); // O mesmo que acima, exceto que o deslocamento deve ser subtraído por 8 (8 bits altos) antes do cálculo

                p_gpiox->CRH |= config << ((pinpos - 8) * 4); // Desloca a configuração para a esquerda pelo bit de deslocamento e escreve o resultado no registro CRH.

            }

        }

    }

}

void sys_gpio_pin_set(GPIO_TypeDef *p_gpiox, uint16_t pinx, uint8_t status) //(status de saída de pino único GPIO)

{

    /*introdução de parâmetros

    p_gpiox aponta para o endereço de registro do GPIOx (x é A, B, C, etc.), pinx representa o pino a ser controlado e status representa o status do pino (0 ou 1).

    */

    if (status & 0X01) // avalia o bit mais baixo de status (ou seja, 0 ou 1) e determina a operação do pino a ser executada

    {

        // Neste momento, execute uma operação OR bit a bit no valor de pinx e na máscara 0xFFFF (ou seja, todos os bits são 1), defina os 16 bits inferiores do registro BSRR como 1 e defina o nível do pino correspondente para alto.

        p_gpiox->BSRR |= pinx;

    }

    outro

    {

        // Neste momento, execute uma operação OR bit a bit no valor de pinx e na máscara 0xFFFF (ou seja, todos os bits são 1), defina os 16 bits inferiores do registro BSRR como 1 e defina o nível do pino correspondente para alto.

        p_gpiox->BSRR |= (uint32_t)pinx << 16;

    }

}

uint8_t sys_gpio_pin_get(GPIO_TypeDef *p_gpiox, uint16_t pinx) // (lê o status do pino único do GPIO)

{

    /*introdução de parâmetros

    p_gpiox aponta para o endereço de registro do GPIOx (x é A, B, C, etc.)

    pinx representa o pin para obter status

    */

    if (p_gpiox->IDR & pinx) // A instrução de julgamento if julga se um determinado bit de IDR (ou seja, os dados do nível do pino) é 1 e determina o estado real do nível do pino

    {

        return 1; // significa que o nível do pino está alto, return 1

    }

    outro

    {

        return 0; // Se o bit for 0, significa que o nível do pino está baixo, return 0.

    }

}

void sys_wfi_set(void) // (entra no estado de baixo consumo de energia)

{

    __ASM volátil("wfi"); // O código usa a instrução assembly wfi, que coloca o processador no modo WFI e espera que um sinal de interrupção seja acionado.

}

void sys_intx_disable(void) // (desliga todas as interrupções)

{

    __ASM volátil("cpsid i"); // O código usa a instrução assembly cpsid i, que limpará o bit de habilitação de interrupção do processador e desabilitará o disparo de todas as interrupções.

}

void sys_intx_enable(void) // (habilita todas as interrupções)

{

    __ASM volátil("cpsie i"); // O código utiliza a instrução assembly cpsie i, que definirá o bit de habilitação de interrupção do processador e permitirá o disparo de solicitações de interrupção.

}

void sys_msr_msp(uint32_t addr) // (define o endereço do topo da pilha)

{

    // (Padrão de interface de software do microcontrolador Cortex)

    __set_MSP(addr); // O código usa a função da biblioteca CMSIS __set_MSP(), que é usada para definir o valor do registro MSP para o parâmetro addr de entrada.

}

void sys_standby(void) // (entra no modo de espera)

{

    RCC->APB1ENR |= 1 << 28; // Habilita o clock do módulo PWR (Power Control) no barramento APB1 no módulo RCC, (desloca 1 << 28 para a esquerda em 28 bits, e obtém 0x10000000 para indicar PWR )

    PWR->CSR |= 1 << 8; // Define o 8º bit (PDDS) do registro CSR do módulo PWR para 1, o que significa entrar no modo standby.

    PWR->CR |= 1 << 2; // Define o bit 2 (ULP) do registro CR do módulo PWR para 1, indicando que o modo ULP (Ultra Low Power) está selecionado, e a operação de entrar no standby modo está ativado.

    PWR->CR |= 1 << 1; // Define o bit 1 (PDDS) do registro CR do módulo PWR para 1, modo PDDS (Power Down Deep Sleep) e inicia a operação de entrada no modo de espera.

    SCB->SCR |= 1 << 2; // Define o bit 2 (SLEEPDEEP) do registro SCR do módulo SCB (System Control Block) como 1, o que significa entrar no estado de hibernação profunda.

    sys_wfi_set(); // (entra no estado de baixo consumo de energia)

}

void sys_soft_reset(void) // (redefinição do software do sistema)

{

    // A operação "ou" de 0X05FA0000 e (uint32_t)0x04 pode obter um valor específico 0x05FA0004, indicando que a reinicialização do software do sistema foi executada.

    // Atribuir este valor ao registro AIRCR do SCB fará com que o processador execute uma reinicialização de software.

    SCB->AIRCR = 0X05FA0000 | (uint32_t)0x04;

}

uint8_t sys_clock_set(uint32_t plln) // (função de configuração do relógio)

{

    uint32_t tentar novamente = 0;

    uint8_t retval = 0;

    // O parâmetro plln indica o coeficiente de multiplicação do clock que precisa ser definido. retry e retval são usados ​​para registrar o número de novas tentativas e o valor de retorno, respectivamente.

    // RCC é um módulo controlador de registro

    RCC->CR |= 0x00010000; // Use a operação "|=" para definir o bit 16 (HSEON) deste registro para 1, indicando que o relógio externo de alta velocidade (HSE) deve ser ligado.

    while (tentar novamente <0XFFF0)

    {

        __nop(); // Instrução de instrução vazia __nop(), para esperar que o relógio externo de alta velocidade esteja pronto.

        if (RCC->CR & (1 << 17) && tentar novamente > 0X8000)

        {

            break; // Se o clock externo de alta velocidade estiver estável e pronto, o bit 17 (HSERDY) do registro de controle do clock será definido como 1 e o loop poderá ser encerrado neste momento.

        }

        tente novamente++;

    }

    if (retry >= 0XFFF0) // Leva um certo tempo para o relógio externo de alta velocidade se estabilizar, então um número máximo de tentativas 0XFFF0 é definido.

    {

        retval = 1; // retval é 1 significa que a configuração do relógio falhou.

    }

    else // Se o relógio externo de alta velocidade estiver estável e pronto, insira a parte principal da configuração do relógio.

    {

        RCC->CFGR = 0X00000400;

        // Define o valor do registrador divisor de clock CFGR para 0X00000400, indicando AHB (Advanced High-Performance Bus) e APB

        // (Advanced Peripheral Bus) não divide a frequência respectivamente, ou seja, as frequências de clock AHB e APB são iguais.

        plln -= 2; // Subtrai 2 do fator de multiplicação do clock de entrada plln,

        RCC->CFGR |= plln << 18; // e desloque-o para a esquerda em 18 bits, e então use a operação "|=" para defini-lo como o bit correspondente [29:24] do registrador CFGR, que significa definir o fator de frequência dos tempos do relógio PLL.

        RCC->CFGR |= 1 << 16; // Define-o para os bits correspondentes [29:24] do registrador CFGR, o que significa definir o fator de multiplicação do clock PLL.

        /* Configura o período de atraso da memória Flash */

        FLASH->ACR = 1 << 4; // Use a operação "ou" para definir o bit 4 (LATENCY) do registro ACR para 1, indicando que o período de atraso da memória Flash está definido para 1 ciclo de clock.

        FLASH->ACR |= 2 << 0; // Use a operação "ou" para definir os bits [2:0] do registro ACR para 2, o que significa usar o atraso HCLK (relógio AHB).

        /*O objetivo da configuração acima é permitir que a memória Flash suporte o clock do sistema a 48MHz. */

        RCC->CR |= 1 << 24; // Use a operação "ou" para definir o bit 24 (PLLON) do registro CR como 1 para habilitar o relógio PLL.

        while (!(RCC->CR >> 25)) // Utilize o loop while para aguardar a estabilização do clock, ou seja, aguardar que o bit de bloqueio do PLL (PLLRDY) do registrador CR se torne 1, indicando que o O relógio PLL está estável.

            ;

        RCC->CFGR |= 2 << 0; // Utilize o loop while para aguardar a estabilização do clock, ou seja, aguardar que o bit de bloqueio do PLL (PLLRDY) do registrador CR se torne 1, indicando que o clock do PLL é estável.

        while (((RCC->CFGR >> 2) & 0X03) != 2) // Use o loop while para esperar que os bits [3:2] do registrador CFGR se tornem 2, indicando que o clock do PLL se estabilizou como o relógio do sistema.

            ;

    }

    return retval; // Finalmente, retorna o status da configuração do relógio, se o valor de retorno for 0, a configuração do relógio foi bem-sucedida, se o valor de retorno for 1, a configuração falhou.

}

void sys_stm32_clock_init(uint32_t plln) // (função de inicialização do relógio)

{

    RCC->APB1RSTR = 0x00000000; // Limpa o registrador de reset do APB1, ou seja, coloca todos os seus bits em 0, de forma a garantir que todos os dispositivos deste barramento estejam em estado de reset quando o clock for inicializado.

    RCC->APB2RSTR = 0x00000000; // Limpa o registrador de reset do APB2, ou seja, coloca todos os seus bits em 0, de forma a garantir que todos os dispositivos deste barramento estejam em estado de reset quando o clock for inicializado.

    RCC->AHBENR = 0x00000014; // Define o registro de habilitação do clock no barramento AHB para habilitar periféricos DMA, GPIOA e GPIOB.

    RCC->APB2ENR = 0x00000000; // Limpa o registro de habilitação do clock do APB2, ou seja, coloca todos os seus bits em 0, o que pode garantir que todos os dispositivos deste barramento não sejam habilitados quando o clock for inicializado.

    RCC->APB1ENR = 0x00000000; // Limpa o registro de habilitação do clock do APB1, ou seja, coloca todos os seus bits em 0, o que pode garantir que todos os dispositivos deste barramento não sejam habilitados quando o clock for inicializado.

    RCC->CR |= 0x00000001; // Define o bit de habilitação do registro de controle de clock RCC para habilitar o clock externo de alta velocidade (HSE).

    RCC->CFGR &= 0xF8FF0000; // Limpa o PLL, o divisor de frequência e os bits de opção de relógio do registro de configuração de relógio RCC.

    RCC->CR &= 0xFEF6FFFF; // Limpa o PLL, o divisor de frequência e os bits de opção de relógio do registro de configuração de relógio RCC.

    RCC->CR &= 0xFFFBFFFF; // Limpa o bit de desabilitação HSE do registrador de controle de clock RCC

    RCC->CFGR &= 0xFF80FFFF; // Limpa o bit multiplicador PLL do registro de configuração do relógio RCC

    RCC->CIR = 0x009F0000; // Limpa o registro de interrupção do relógio RCC.

    sys_clock_set(plln); // Use a função sys_clock_set para definir o fator de multiplicação do PLL e escolha se deseja usar o PLL como relógio do sistema.

#ifdef VECT_TAB_RAM

    sys_nvic_set_vector_table(SRAM_BASE, 0x0); // Seleciona o endereço da tabela de vetores na RAM para salto do programa do usuário e processamento de interrupção.

#outro

    sys_nvic_set_vector_table(FLASH_BASE, 0x0); // Selecione o endereço da tabela de vetores em FLASH para salto do programa do usuário e processamento de interrupção.

#fim se

}

Acho que você gosta

Origin blog.csdn.net/JohnJill/article/details/130546178
Recomendado
Clasificación