stm32怎么通过printf发送数据到上位机

如题所述

这个需要通过STM32的串口。

①如果你的上位机是电脑,那么需要一个USB转TTL,TTL端接STM32串口。

②编写STM32串口驱动(这个很容易的,配置引脚和串口)

③通过标准库的printf或自己编写printf与串口驱动对接。

我以前做智能小车写了一份串口驱动,你可以自己看然后改一下:

(或者可以用库函数,百度很容易找到,我不太喜欢库函数)


/*******************usart_asm.s*******************/

;****usart驱动,汇编版****

USART1 EQU 0X40013800

USART2 EQU 0x40004400

DROS EQU 0X04

SROS EQU 0X00


;接口声明

EXPORT printChar

EXPORT printStr

EXPORT printNum

EXPORT SelectUsart

;接口声明,END


;引用声明

IMPORT Div_U32

;引用声明,end


;数据区

 AREA USART_ADDRESS,DATA,READWRITE

Cur_Usart DCD USART2 ;当前usart地址存储,默认为usart2

Num_Buffer SPACE 12 ;定义10byte缓冲堆栈

;数据区,end


 

 AREA USART_CODE,CODE,READONLY

;SelectUsart,选择Usart,参数2:usart器件代号(1=usart1,非1=usart2)

SelectUsart

STMFD SP!,{R1,LR} ;入栈

LDR R1,=Cur_Usart ;读入usart地址暂存器地址

CMP R0,#1

BNE U2

U1 LDR R0,=USART1

B SETSR

U2 LDR R0,=USART2

SETSR

STR R0,[R1]

LDMFD SP!,{R1,PC} ;出栈

;SelectUsart,end



;***printChar ,参数1:char

printChar

STMFD SP!,{R1-R2,LR} ;入栈

LDR R1,=Cur_Usart

LDR R1,[R1] ;载入Usart地址

CHR_WAIT

LDR R2,[R1,#SROS] ;读状态寄存器

TST R2,#0X80

BEQ CHR_WAIT ;等待上次传输完成

STRB R0,[R1,#DROS] ;写入

LDMFD SP!,{R1-R2,PC} ;出栈

;***printChar ,end



;***printStr ,参数1:str

printStr

STMFD SP!,{R1-R3,LR} ;入栈

LDR R1,=Cur_Usart

LDR R1,[R1] ;载入Usart地址

SEND_STR

LDR R2,[R1,#SROS]

TST R2,#0X80

BEQ SEND_STR ;等待上次传输完成

LDRB R3,[R0],#1 ;将指针(R0)处字符读入R3

STRB R3,[R1,#DROS];写入

CMP R3,#0

BNE SEND_STR;循环直到结束符'\0'

LDMFD SP!,{R1-R3,PC} ;出栈

;***printStr ,end



;printNum ,参数1:NUM,参数2:usart器件代号(1=usart1,非1=usart2)

printNum

STMFD SP!,{R1-R5,LR} ;入栈

LDR R1,=10 ;除数为10,被除数已在R0中

LDR R3,=Num_Buffer ;载入缓冲区首地址

LDR R4,=0

LDR R5,=0 ;负数指示器,1=负数

TST R0,#0x80000000

BEQ STR_NUM ;正数

EOR R0,#0xFFFFFFFF ;负数,反转

ADD R0,#1

LDR R5,=1

STR_NUM

BL Div_U32

ADD R2,R2,#0x30 ;转换为char

STRB R2,[R3],#1 ;余数存入缓冲区

ADD R4,R4,#1 ;计数+1

CMP R0,#0

BNE STR_NUM ;直到商为0

CMP R5,#1

LDR R1,=Cur_Usart

LDR R1,[R1] ;载入Usart地址

BNE SEND_NUM ;正数

LDR R2,='-'

STRB R2,[R3],#1 ;'-'号存入缓冲区

ADD R4,R4,#1 ;计数+1

SEND_NUM

LDRB R0,[R3,#-1]!

SEND_WAIT

LDR R2,[R1,#SROS] ;读状态寄存器

TST R2,#0X80

BEQ SEND_WAIT ;等待上次传输完成

STRB R0,[R1,#DROS] ;写入

SUBS R4,R4,#1

BNE SEND_NUM

LDMFD SP!,{R1-R5,PC} ;出栈

;printNum ,end



 END

 

usart.h

/*********************************************
USART2{TX=PA2,Rx=PA3},USART1{TX=PA9,Rx=PA10}
*********************************************/
#ifndef USART_H_
#define USART_H_

#include "Common.h"
#include "I2C.h"
#include "SG90.h"
#include "SRF05.h"

#define USART_RECV_BUFF_SIZE 15

#define Pclk1_36MHz 36000000 //其他USART
#define Pclk2_72MHz 72000000 //USART1
#define USART_PSC 16  //Prescaler Value 时钟预分频

//#define CrLf {0x0D,0x0A,0x00}

void usart_init(void);


u32 calcBRRDiv(u32 BaudRate,u32 Pclk);

extern void SelectUsart(u32 Usart);//Usart为usart代号 1为usart1,非1为usart2
extern void printChar(char ch);//由汇编实现
extern void printStr(char * str);
extern void printNum(s32 num);

#ifdef DEBUG
void printf(char* s,...);
#endif

#endif


usart.c

#include "usart.h"
#include "stdarg.h"
//串口

/***私有函数声明***/
u32 calcBRRDiv(u32 BaudRate,u32 Pclk);

//------------------------------------------------------------------
//函数名:void usart_init(void)
//输入参数:无
//返回参数:无
//说明:初始化串口寄存器
//备注:DEBUG模式下将会初始化USART1
//------------------------------------------------------------------
void usart_init(void)
{
    //Usart2 配置
    USART2->BRR = calcBRRDiv(9600,Pclk1_36MHz);//(USART_BRR)
    USART2->GTPR = USART_PSC/2;//(USART_GTPR)
    USART2->CR1 = 0x0000202C;//(USART_CR1)0x000020EC
    USART2->CR2 = 0;  //(USART_CR2)
    USART2->CR3 = 0;  //(USART_CR3)
#ifdef DEBUG
//Usart1 配置
    USART1->BRR = calcBRRDiv(9600,Pclk2_72MHz);//(USART_BRR)
    USART1->GTPR = USART_PSC/2;//(USART_GTPR)
    USART1->CR1 = 0x0000202C;//(USART_CR1)
#endif
}


#ifdef DEBUG

void printf(char* format,...)
{
va_list args;

va_start(args,format);

while(*format)
{
if(*format=='%')
{
switch(*++format)
{
case 'c':
printChar((char)va_arg(args,int));
break;
case 's':
printStr(va_arg(args,char*));
break;
case 'd':
printNum((s32)va_arg(args,s32));
break;
case '%':
printChar('%');
break;
}
}
else
{
printChar(*format);
}
format++;
}

va_end(args);
}
#endif

//------------------------------------------------------------------
//函数名:void USART2_IRQHandler(void)
//输入参数:null
//返回参数:null
//说明:串口接收中断服务
//------------------------------------------------------------------
const uchar BTCtrl_DataFrameHeader[5]={0xa5,0x5a,0x11,0xf5,0};//蓝牙控制数据帧头
uchar ser_dat[USART_RECV_BUFF_SIZE];//数据缓冲区
bool bProcessCompleted=true;//判断一帧数据是否处理完成,当一帧数据接收完毕,则该变量被置为false

enum BTProcessingFlag/*蓝牙数据接收模式*/
{
    CheckingFrameHeader,//检测数据帧头
    ReceivingData//接收数据包
};
void USART2_IRQHandler(void)
{
    static uchar ser_x=0;
    static uchar mat_x=0;//match x
    static uchar sum=0;
    static enum BTProcessingFlag dflag=CheckingFrameHeader;

    if (bProcessCompleted)//!上一帧数据处理完成之后
    {
        if (USART2->SR & 1<<5)//!判断读寄存器是否非空
        {
            if (dflag==CheckingFrameHeader)
            {
                if (USART2->DR==BTCtrl_DataFrameHeader[mat_x])
                {
                    mat_x++;
                }
                else
                {
                    mat_x=0;
                }
                if (BTCtrl_DataFrameHeader[mat_x]==0)//!数据头结束,更换模式准备接收数据
                {
                    dflag=ReceivingData;
                    ser_x=0;
                    mat_x=0;
                    sum=0;
                }
            }
            else if (dflag==ReceivingData)
            {
                ser_dat[ser_x]=USART2->DR;
                if (ser_x==USART_RECV_BUFF_SIZE-1)//!只接收USART_RECV_BUFF_SIZE字节
                {
                    sum+=BTCtrl_DataFrameHeader[2];
                    sum+=BTCtrl_DataFrameHeader[3];
                    dflag=CheckingFrameHeader;//!切换接收模式
                    if (ser_dat[USART_RECV_BUFF_SIZE-1]==sum)//!数据检验
                    {
                        bProcessCompleted=false;//!数据正确,置接收完成标志
USART2->CR1 &= ~(1<<13);//!停止usart2
                    }
                }
                sum+=ser_dat[ser_x];//!数据验证
ser_x++;
            }
        }
    }
}

//------------------------------------------------------------------
//函数名:u32 calcBRRDiv(u32 BaudRate,u32 Pclk)
//输入参数:BaudRate=波特率,Pclk=RCC时钟频率
//返回参数:应置入寄存器的值
//说明:计算相应波特率以及时钟频率对应的BRRDiv寄存器中应该填入的值
//备注:计算方法参照(分数波特率的产生)
//------------------------------------------------------------------
u32 calcBRRDiv(u32 BaudRate,u32 Pclk)
{
    u32 div_mant;
    u32 div_frac;
    float frac;
    div_mant=Pclk/(USART_PSC*BaudRate);
    frac=(float)Pclk/(USART_PSC*BaudRate);
    frac-=div_mant;
    frac*=USART_PSC;
    div_frac=(u32)frac;
    div_frac+=(frac-div_frac)>=0.5?1:0;//四舍五入

    if (div_frac==USART_PSC)//满USART_PSC进位
    {
        div_frac=0;
        div_mant++;
    }
    div_mant<<=4;
    div_mant|=div_frac;
    return div_mant;
}

温馨提示:答案为网友推荐,仅供参考
相似回答