STM32L476G_STLink_UART 虚拟串口(板上usb USER接口直接USB连接电脑)的移植

源代码:https://github.com/jimingkang/STM32L476_BSP

在本地电脑C:\Users\jmmy\Downloads\raspi_STM\STM32L476G_STLink_UART_Debug\STM32L476G_STLink_UART_Debug

这里采用裸机程序,没有借用库

1.)main.czjie直接初始化,然后调用(UART2_Init,USART_Write都在UART.c中)

UART2_Init(); //硬件初始化

n = sprintf((char *)buffer, "hello kaka \r\n");
USART_Write(USART2, buffer, n);

 

2.)UART.c

#include "UART.h"
// UART Ports:
// ===================================================
// PA.0 = UART4_TX (AF8)   |  PA.1 = UART4_RX (AF8)      
// PB.6 = USART1_TX (AF7)  |  PB.7 = USART1_RX (AF7)
// PD.5 = USART2_TX (AF7)  |  PD.6 = USART2_RX (AF7)   //这里是GPIO D ,可见虚拟串口通过GPOID67转化为USB接口信号然后连接电脑;而不是常见接到GPIOB 9,10,通过GPIOB 9,10连接硬件串口rx,tx线路(注意GPIO只是通用信号,只是负责把cpu线路导出来,具体取决于芯片设计者把他当什么用处,这里把它当串口,它就把串口信号导出连接到tx,rx,至于外部串口电路,那就不管,由更外面的电路板开发人员来负责设计rx,tx的外部连接,比如中国的电路板小公司)

void UART2_Init(void) {
    // Enable the clock of USART 1 & 2
    RCC->APB1ENR1 |= RCC_APB1ENR1_USART2EN;  // Enable USART 2 clock        
    
    // Select the USART1 clock source
    // 00: PCLK selected as USART2 clock
    // 01: System clock (SYSCLK) selected as USART2 clock
    // 10: HSI16 clock selected as USART2 clock
    // 11: LSE clock selected as USART2 clock
    RCC->CCIPR &= ~RCC_CCIPR_USART2SEL;
    RCC->CCIPR |=  RCC_CCIPR_USART2SEL_0;
    
    UART2_GPIO_Init();//由前面的红色部分,可见要配置GPIO
    USART_Init(USART2);//真正的uart硬件配置
    

//这里没用到中断接收发送,直接阻塞式
    //NVIC_SetPriority(USART2_IRQn, 0);            // Set Priority to 1
    //NVIC_EnableIRQ(USART2_IRQn);                    // Enable interrupt of USART1 peripheral
}

void UART2_GPIO_Init(void) {
    
    // Enable the peripheral clock of GPIO Port
    RCC->AHB2ENR |=   RCC_AHB2ENR_GPIODEN;
    
    // ********************** USART 2 ***************************
    // PD5 = USART2_TX (AF7)
    // PD6 = USART2_RX (AF7)
    // Alternate function, High Speed, Push pull, Pull up
    // **********************************************************
    // Input(00), Output(01), AlterFunc(10), Analog(11)
    GPIOD->MODER   &= ~(0xF << (2*5));    // Clear bits
    GPIOD->MODER   |=   0xA << (2*5);              
    GPIOD->AFR[0]  |=   0x77<< (4*5);           
    // GPIO Speed: Low speed (00), Medium speed (01), Fast speed (10), High speed (11)
    GPIOD->OSPEEDR |=   0xF<<(2*5);                          
    // GPIO Push-Pull: No pull-up, pull-down (00), Pull-up (01), Pull-down (10), Reserved (11)
    GPIOD->PUPDR   &= ~(0xF<<(2*5));
    GPIOD->PUPDR   |=   0x5<<(2*5);                    
    // GPIO Output Type: Output push-pull (0, reset), Output open drain (1)
    GPIOD->OTYPER  &=  ~(0x3<<5) ;           
}

//真正的uart硬件配置
void USART_Init (USART_TypeDef * USARTx) {
    // Default setting:
    //     No hardware flow control, 8 data bits, no parity, 1 start bit and 1 stop bit        
    USARTx->CR1 &= ~USART_CR1_UE;  // Disable USART
    
    // Configure word length to 8 bit
    USARTx->CR1 &= ~USART_CR1_M;   // M: 00 = 8 data bits, 01 = 9 data bits, 10 = 7 data bits
    
    // Configure oversampling mode: Oversampling by 16
    USARTx->CR1 &= ~USART_CR1_OVER8;  // 0 = oversampling by 16, 1 = oversampling by 8
    
    // Configure stop bits to 1 stop bit
    //   00: 1 Stop bit;      01: 0.5 Stop bit
    //   10: 2 Stop bits;     11: 1.5 Stop bit
    USARTx->CR2 &= ~USART_CR2_STOP;   
                                    
    // CSet Baudrate to 9600 using APB frequency (80,000,000 Hz)
    // If oversampling by 16, Tx/Rx baud = f_CK / USARTDIV,  
    // If oversampling by 8,  Tx/Rx baud = 2*f_CK / USARTDIV
  // When OVER8 = 0, BRR = USARTDIV
    // USARTDIV = 80MHz/9600 = 8333 = 0x208D
    USARTx->BRR  = 0x208D; // Limited to 16 bits

    USARTx->CR1  |= (USART_CR1_RE | USART_CR1_TE);      // Transmitter and Receiver enable
    
  if (USARTx == UART4){    
        USARTx->CR1 |= USART_CR1_RXNEIE;              // Received Data Ready to be Read Interrupt  
        USARTx->CR1 &= ~USART_CR1_TCIE;                // Transmission Complete Interrupt
        USARTx->CR1 &= ~USART_CR1_IDLEIE;              // Idle Line Detected Interrupt
        USARTx->CR1 &= ~USART_CR1_TXEIE;               // Transmit Data Register Empty Interrupt
        USARTx->CR1 &= ~USART_CR1_PEIE;                // Parity Error Interrupt
        USARTx->CR1 &= ~USART_CR2_LBDIE;                // LIN Break Detection Interrupt Enable
        USARTx->CR1 &= ~USART_CR3_EIE;                    // Error Interrupt Enable (Frame error, noise error, overrun error)
        //USARTx->CR3 &= ~USART_CR3_CTSIE;                // CTS Interrupt
    }

    if (USARTx == USART2){
        USARTx->ICR |= USART_ICR_TCCF;
        USART1->CR3 |= USART_CR3_DMAT | USART_CR3_DMAR;
    }
    
    USARTx->CR1  |= USART_CR1_UE; // USART enable                 
    
    while ( (USARTx->ISR & USART_ISR_TEACK) == 0); // Verify that the USART is ready for reception
    while ( (USARTx->ISR & USART_ISR_REACK) == 0); // Verify that the USART is ready for transmission
}


uint8_t USART_Read (USART_TypeDef * USARTx) {
    // SR_RXNE (Read data register not empty) bit is set by hardware
    while (!(USARTx->ISR & USART_ISR_RXNE));  // Wait until RXNE (RX not empty) bit is set
    // USART resets the RXNE flag automatically after reading DR
    return ((uint8_t)(USARTx->RDR & 0xFF));
    // Reading USART_DR automatically clears the RXNE flag
}

void USART_Write(USART_TypeDef * USARTx, uint8_t *buffer, uint32_t nBytes) {
    int i;
    // TXE is cleared by a write to the USART_DR register.
    // TXE is set by hardware when the content of the TDR
    // register has been transferred into the shift register.
    for (i = 0; i < nBytes; i++) {
        while (!(USARTx->ISR & USART_ISR_TXE));       // wait until TXE (TX empty) bit is set
        // Writing USART_DR automatically clears the TXE flag     
        USARTx->TDR = buffer[i] & 0xFF;
        USART_Delay(300);
    }
    while (!(USARTx->ISR & USART_ISR_TC));             // wait until TC bit is set
    USARTx->ISR &= ~USART_ISR_TC;
}   
 

void USART_Delay(uint32_t us) {
    uint32_t time = 100*us/7;    
    while(--time);   
}

void USART_IRQHandler(USART_TypeDef * USARTx, uint8_t *buffer, uint32_t * pRx_counter){
    if(USARTx->ISR & USART_ISR_RXNE) {                        // Received data                         
        buffer[*pRx_counter] = USARTx->RDR;         // Reading USART_DR automatically clears the RXNE flag
        (*pRx_counter)++;  
        if((*pRx_counter) >= BufferSize )  {
            (*pRx_counter) = 0;
        }   
    } else if(USARTx->ISR & USART_ISR_TXE) {
         //USARTx->ISR &= ~USART_ISR_TXE;            // clear interrupt
        //Tx1_Counter++;
    } else if(USARTx->ISR & USART_ISR_ORE) {            // Overrun Error
        while(1);
    } else if(USARTx->ISR & USART_ISR_PE) {                // Parity Error
        while(1);
    } else if(USARTx->ISR & USART_ISR_PE) {                // USART_ISR_FE    
        while(1);
    } else if (USARTx->ISR & USART_ISR_NE){             // Noise Error Flag
        while(1);     
    }    
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值