¿Cómo envía STM32 datos al host a través de printf?
Esto requiere pasar el puerto serie STM32.
① Si el host es una computadora, necesita un puerto serie USB a TTL o TTL a STM32.
②Escriba un controlador de puerto serie STM32 (esto es muy simple, solo configure los pines y el puerto serie)
③Utilice el printf de la biblioteca estándar o escriba su propio printf y línea de puerto serie acoplamiento del conductor del puerto.
MFD SP!{R1-R3, LR}; en
LDR R1,=Cur_ Usart
LDR R1, [R1];
LDR R2, [R1, #SROS]
TST R2, #0X80
BEQ SEND_STR; Espera a que se complete la última transferencia
LDRB R3, [R0], #1; Leer los caracteres del puntero (R0) en R3
STRB R3, [R1, #DROS]; Escribir
CMP R3; , #0
BNE SEND_STR ; Bucle hasta el terminador '\0'
LDMFD SP! , {R1-R3, PC}; Fuera de la pila
; ***printStr, end.***printStr, end
; : código de dispositivo usart (1=usart1, no 1=usart2)
printNum
STMFD SP!{R1-R5, LR}; R1, .=10; El divisor es 10 y el divisor ya está en R0
LDR R3, =Num_Buffer La primera dirección del buffer de carga
LDR R4, =0<; /p>
LDR R5, =0; indicador negativo, 1=negativo
TST R0, #0x80000000
BEQ STR_ NUM; EOR R0, #0xFFFFFFFF; número negativo, inverso
ADD R0, #1
LDR R5, =1
STR_NUM
BL Div_U32
AGREGAR R2, R2, #0x30; Convertir a carácter
STRB R2, [R3], #1; Almacenar el resto en el búfer
AGREGAR R4, R4 , #1 ; cuenta 1
CMP R0, #0
BNE STR_NUM; hasta que el cociente sea 0
CMP R5, #1
LDR R1, =Cur_Usart
LDR R1, [R1] ; Cargar dirección Usart
BNE SEND_NUM ; ='-'
STRB R2, [R3], #1; el número '-' se almacena en el búfer
ADD R4, R4, #1;
ENVIAR _NUM
¡LDRB R0, [R3, #-1]!
SEND_WAIT
LDR R2, [R1, #SROS]; leer registro de estado
TST R2, #0X80
BEQ SEND_WAIT; espere a que se complete la última transmisión
STRB R0, [R1, #DROS] escriba
SUBS R4, R4, #1
BNE SEND_NUM
LDMFD SP!{R1-R
5, PC}; fuera de la pila
; printNum, end END
usart.h/****************** **************************
USART2{TX=PA2, Rx=PA3}, USART1{TX=PA9 , Rx=PA10}
*************************************** **** *******
#ifndef?USART_H_
#define?USART_H_
#include?"Common.h" p>
#include?"I2C.h"
#include?"SG90.h"
#include?"SG90.h"
#include?" Common.h"
#include?"SG90.h"
#include?"SRF05.h"
#define?USART_RECV_BUFF_SIZE? 15
#define?Pclk1_36MHz?36000000?//otros USART
#define?Pclk2_72MHz?72000000?//USART1
#define?USART_PSC?// ¿Preescalador? ¿valor? Preescalador de reloj
//#define?CrLf?{0x0D, 0x0A, 0x00}
void?usart_init(void);
u32?calcBRRDiv (u32? BaudRate, u32?Pclk);
extern?void?SelectUsart(u32?Usart); //Usart es el nombre clave de usart? 1 significa usart1, no-1 significa usart2
extern?void?printChar(char?ch); //implementado por ensamblaje
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"void?printf(char*?formato,...)
{
va_list?args;
va_start(args, formato);
p>while(*formato)
{
if(*formato=='')
{
cambiar (* formato)
{
case?'c':
printChar((char)va_arg(args, int)); p>
descanso;
caso?'s:
printStr(va_arg( args, char*));
romper;
caso? 'd':
printNum((s32)va_arg(args, s32));
romper; >
caso?'':
printChar(''
descanso
}
}
else
{
printChar(*formato);
}
formato; }
va_end(args);
}
#endif
//----------- -------------------------------------------------- -----
//Nombre de la función: void?USART2_IRQHandler( void)
//Parámetros de entrada: vacío
/Parámetros de retorno: vacío p>
/Descripción: Servicio de interrupción de recepción del puerto serie
//-------------------------- -- -------------------------------- ------
const?uchar? BTCtrl_DataFrameHeader [5]={0xa5, 0x5a, 0x11, 0xf5, 0}; //Encabezado del marco de datos de control de Bluetooth
uchar?ser_dat[USART_RECV_BUFF_SIZE] //Búfer de datos
bool? bProcessCompleted=true; //Determina si se procesa la trama Cuando se recibe la trama, la variable se establece en false
enum?BTProcessingFlag/*Modo de recepción de datos Bluetooth**
{
CheckingFrameHeader, //Comprobando el encabezado del marco de datos
ReceivingData//Recibiendo paquete de datos
};
void?USART2_IRQHandler(void)
{
static?uchar?ser_x=0;
static?uchar?mat_x=0;//match?x
static?uchar ?sum =0;
estático?Después de completar el procesamiento de datos del último cuadro
{
if?(USART2-gt;SR?amp;?1lt ;es; 5)//! Determine si el registro de lectura no está vacío
{
if?(dflag===CheckingFrameHeader)
{
if? ( USART2-gt;DR==BTCtrl_DataFrameHeader[mat_x])
{
mat_x;
}
else
{
mat_x=0;
}
si?(BTCtrl_DataFrameHeader[mat_x]==0)//! El encabezado de datos finaliza, cambia el modo y prepárate para recibir datos
{
dflag=ReceivingData;
ser_x=0;<
/p>
mat_x=0;
suma=0;
}
}
else?if?( dflag ==RecibiendoDatos)
{
ser_dat[ser_x]=USART2-gt;DR;
if?(ser_x==USART_RECV_BUFF_SIZE-1)//! Sólo se reciben USART_RECV_BUFF_SIZE bytes
{
sum =BTCtrl_DataFrameHeader[2];
sum =BTCtrl_DataFrameHeader[3];
dflag= Comprobación de encabezado de marco; //! Cambiar modo de recepción
if?(ser_dat[USART_RECV_BUFF_SIZE-1]==sum)//! Verificación de datos
{
bProcessCompleted=false; Los datos son correctos, configure el indicador de finalización de recepción
USART2-gt;CR1?amp;=?~(1lt;lt;13); //! Deja de usart2
}
}
sum =ser_dat[ser_x] //! Validación de datos
ser_x;
}
}
}
}
//------------------------------------------------ ------------------
//Nombre de la función: u32?calcBRRDiv(u32?BaudRate, u32?Pclk)
/ /Parámetro de entrada: BaudRate=BaudRate, Pclk=frecuencia de reloj RCC
//Parámetro de retorno: el valor que debe colocarse en el registro
//Descripción: Calcula la suma de la velocidad en baudios del registro BRRDiv Frecuencia de reloj: ver método de cálculo (generación de velocidad de baudios fraccionaria)
//------------------------- - ---------------------------------------
u32?calcBRRDiv ( u32?BaudRate,u32?Pclk)
{
u32?div_mant;
u32?div_frac;
flotador?frac;
div_mant=Pclk/(USART_PSC*BaudRate);
frac=(float)Pclk/(USART_PSC*BaudRate);
frac-=div_mant; /p>
frac=(float)Pclk/(USART_PSC*BaudRate);
frac-=div_mant
p>
frac*=USART_PSC
p>
div_frac=(u32 )frac;
div_frac =(frac-div_frac)gt;=0.5?1:0; //redondear hacia arriba
if?(div_frac) ==USART_PSC)//redondeo USART_PSC completo
{
div_frac=0;
div_mant;
}
div_mantlt;lt;=4;
div_mant|=div_frac;
¿regresar?