STM32F103C8T6串口通信-将上位机发给MCU的数据发回给上位机

#ifndef __USART_H__
#define __USART_H__

#include "stm32f10x.h"
#include <stdio.h>//重定向的函数要用

#define USART1_SEND_BYTE_NUM  512//定义发送字节数

extern uint16_t USART1_RX_STATE;
extern uint16_t USART1_SEND_BYTE[];

void USART1_GPIO_Init(void);
int fputc(int ch, FILE *f);


#endif

usart.h

#include "usart.h"


uint16_t USART1_RX_STATE = 0;//定义标志位
uint16_t USART1_SEND_BYTE[USART1_SEND_BYTE_NUM];

void USART1_GPIO_Init(void)
{
    //1.指定并配置GPIO端口
    //2.配置串口1
    //3.使能端口时钟,具体的复用功能时钟
    //4.使能串口1
    GPIO_InitTypeDef   GPIO_InitStruct;
    USART_InitTypeDef  USART_InitStruct;

    //PA9 复用功能USART1 TX---需要配置为复用推挽输出--具体模式说在参考手册GPIO章节能查询到,我并未查到
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; 
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;

    //使能时钟-端口时钟,复用功能时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);

    GPIO_Init(GPIOA, &GPIO_InitStruct);

    //PA10 复用功能USART1 RX---需要配置为浮空输入  --具体模式说在参考手册GPIO章节能查询到,我并未查到

    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
//    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; 
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;

    GPIO_Init(GPIOA, &GPIO_InitStruct);

    //配置USART1
    USART_InitStruct.USART_BaudRate = 9600;//常用波特率值
    USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
    USART_InitStruct.USART_WordLength = USART_WordLength_8b;
    USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStruct.USART_Parity = USART_Parity_No;
    USART_InitStruct.USART_StopBits = USART_StopBits_1;

    USART_Init(USART1, &USART_InitStruct);

    //使能串口1
    USART_Cmd(USART1, ENABLE);

    //串口中断设置
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//配置接收非空产生中断
}

//实现串口打印功能需要调用printf函数,需要重定向fputc函数

int fputc(int ch, FILE *f)
{
    while(USART_GetFlagStatus(USART1, USART_FLAG_TC) != SET);
    USART_SendData(USART1, (unsigned char)ch);//该函数本来是把要打印的字符串ch输出到数据流中;被串口从中拿到数据ch的拷贝,并发通过USART_SendData发送到数据输出寄存器USART_DR
//    while(USART_GetFlagStatus(USART1, USART_FLAG_TC) != SET);//数据发送到USART_DR时,USART_FLAG_TC会标志位置高;USART_GetITStatus函数一般是用在中断里确认是哪种中断
//因为这句放下面会经常出现缺少一个字符,所以移动到上面了,不知道啥原因

    return ch;    //数据继续发送到数据流中
}

//void USART1_Send(uint16_t msg)
//{
//    
//}

usart.c

 

#ifndef __NVIC_H__
#define __NVIC_H__

#include "stm32f10x.h"

void NVIC_GPIO_Init(void);



#endif

nvic.h

 

#include"nvic.h"

void NVIC_GPIO_Init(void)
{
    NVIC_InitTypeDef   NVIC_InitStruct;
    NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority  = 2;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

    NVIC_Init(&NVIC_InitStruct);
}

nvic.c

 

 

#include "stm32f10x_it.h"
#include "usart.h"


extern uint16_t USART1_RX_STATE;
extern uint16_t USART1_SEND_BYTE[];


void USART1_IRQHandler(void)
{
    uint8_t res = 0;
    //进入该中断,说明数据接收寄存器RDR接收到数据
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)//  更像是确认是否是接收非空中断;  接收数据寄存器RDR接收到数据时
    {
        res = USART_ReceiveData(USART1);
        if((USART1_RX_STATE & 0x8000) == 0)    //如果最高位为0,说明没有接收完成
        {
            if(USART1_RX_STATE&0x4000)//次高位为1情况下
            {
                if(res == 0x0a)    //次高位为1情况下,如果收到0x0a,需要最高位标志位置1
                {
                    USART1_RX_STATE |= 0x8000;
                }
                else //次高位已经收到0X0D,最后一个字节却不是0X0A,数据都不要了
                {
                     USART1_RX_STATE = 0;//次高位已经收到0X0D,最后一个字节却不是0X0A,数据都不要了
                }
            }
            else//次高位并没有置1,没有收到0x0d
            {
                if(res == 0x0d)              //如果这一个数据正好是0x0d,则次高位置1
                {
                    USART1_RX_STATE |= 0x4000;
                }
                else  //这个数据并不是0X0D,则是USART1_RX_STATE&0x3fff之前的接收序号数据
                {
                     USART1_SEND_BYTE[USART1_RX_STATE&0x3fff] = res;
                     USART1_RX_STATE ++;
                     if(USART1_RX_STATE > USART1_SEND_BYTE_NUM-1)
                    {
                         USART1_RX_STATE = 0;
                    }
                }
                
            }
             
        }
//        else 
//        {
//            
//            
//        }
    }
}
stm32f10x_it.c

USART_GetITStatus一般用在中断里作为判断使用,和USART_GetFlagStatus要区分


#include "stm32f10x.h"
#include "usart.h"
#include "nvic.h"
//mcu transmit data to PC repeatedly ,while PC transmit data to MCU,then MCU will transmit the data what the PC transmit;
//MCU重复不断给PC发数据,当PC给MCU发数据时,MCU会把收到的信息发回给PC



int main(void)
{
    uint8_t t,len;
    NVIC_GPIO_Init();
    USART1_GPIO_Init();
    printf("hello,world!\r\n");
    while(1)
    {
        if(USART1_RX_STATE&0x8000)
        {
            len =  USART1_RX_STATE&0x3fff;
            for(t = 0; t < len; t++)
            {
                USART_SendData(USART1, USART1_SEND_BYTE[t]);
                while(USART_GetFlagStatus(USART1, USART_FLAG_TC) != SET);
            }

            USART1_RX_STATE = 0;
        }
    }
}

main.c

 

 

posted @ 2025-03-01 19:41  了解2号  阅读(350)  评论(0)    收藏  举报