包含:WIFI模块、GPS模块、语言模块、调试信息接口。
一、硬件连接
huart4( PA0、 PA1 )与GPS模块连接。
huart3(PB10、PB11)与ESP8266模块连接。
huart2( PA2、 PA3 )与语音模块连接。
huart1(PB14、PB15)与PC端连接,用于打印调试信息。
二、串口配置代码
2.1 开启中断:
开启串口的接收中断 or 空闲中断。
cpp
/* 该函数会开启接收中断:标志位UART_IT_RXNE,并且设置接收缓冲以及接收缓冲接收最大数据量 */
HAL_UART_Receive_IT(&huart1, (uint8_t *)g_rx_buffer, 1);
// __HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE);
// HAL_UART_Receive_DMA(&huart3,(uint8_t*)ATCmdRxBuffer,ATCmdRxBuffe_MAX_SIZE); //重新启动DMA接收
__HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE); //使能IDLE中断
HAL_UART_Receive_DMA(&huart2, voiceBuf, voiceBuf_MAX_SIZE);
//HAL_UART_Receive_DMA(&huart3, (uint8_t *)g_rx_buffer, 1);
__HAL_UART_ENABLE_IT(&huart3, UART_IT_RXNE); /* 使能UART接收中断 */
__HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE); /* 使能UART总线空闲中断 */
2.2 中断函数:
cpp
/* USER CODE BEGIN 1 */
void HAL_UART_MyIdleCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART2)
{
Voice_Length = voiceBuf_MAX_SIZE - __HAL_DMA_GET_COUNTER(&hdma_usart2_rx);
flag_voice = 1; // 设置接收完成标志
}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) // 串口接收完成中断回调函数
{
if (huart->Instance == USART1) /* 如果是串口1 */
{
if ((myHexapodRx.recv_end_flag & 0x8000) == 0) /* 接收未完成 1000 0000 0000 0000 */
{
if (myHexapodRx.recv_end_flag & 0x4000) /* 接收到了0x0D /r 0100 0000 0000 0000 */
{
if (g_rx_buffer[0] != 0x0a) /* \n 0x0A*/
{
myHexapodRx.recv_end_flag = 0; /* 接收错误,重新开始 */
}
else
{
myHexapodRx.recv_end_flag |= 0x8000; /* 接收完成了 */
}
}
else /* 还没收到0X0D */
{
if (g_rx_buffer[0] == 0x0d)
{
myHexapodRx.recv_end_flag |= 0x4000;
}
else
{ //0011 1111 1111 1111
myHexapodRx.HexapodRxBuf[myHexapodRx.recv_end_flag & 0X3FFF] = g_rx_buffer[0];
myHexapodRx.recv_end_flag++;
if (myHexapodRx.recv_end_flag > (HexapodRxBuf_MAX_SIZE - 1))
{
myHexapodRx.recv_end_flag = 0; /* 接收数据错误,重新开始接收 */
}
}
}
}
HAL_UART_Receive_IT(&huart1, (uint8_t *)g_rx_buffer, 1);
}
if (huart->Instance == USART2)
{
HAL_UART_Receive_DMA(&huart2, (uint8_t *)voiceBuf, voiceBuf_MAX_SIZE);
}
三、功能模块
3.1 ESP8266模块
3.1.1 atk_ESP8266D
atk_mw8266d_usart.c
cpp
#include "atk_mw8266d_usart.h"
#include "usart.h"
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
g_uart_rx_frame myATCmdRx = {0};
static uint8_t g_uart_tx_buf[ATK_MW8266D_UART_TX_BUF_SIZE]; /* ATK-MW8266D UART发送缓冲 */
/**
* @brief ATK-MW8266D UART printf
* @param fmt: 待发送的数据
* @retval 无
*/
void atk_mw8266d_uart_printf(char *fmt, ...)
{
va_list ap;
uint16_t len;
va_start(ap, fmt);
vsprintf((char *)g_uart_tx_buf, fmt, ap);
va_end(ap);
len = strlen((const char *)g_uart_tx_buf);
HAL_UART_Transmit(&g_uart_handle, g_uart_tx_buf, len, HAL_MAX_DELAY);
//HAL_UART_Transmit_IT(&g_uart_handle, g_uart_tx_buf, sizeof(g_uart_tx_buf));
}
/**
* @brief ATK-MW8266D UART重新开始接收数据
* @param 无
* @retval 无
*/
void atk_mw8266d_uart_rx_restart(void)
{
myATCmdRx.sta.len = 0;
myATCmdRx.sta.finsh = 0;
}
/**
* @brief 获取ATK-MW8266D UART接收到的一帧数据
* @param 无
* @retval NULL: 未接收到一帧数据
* 其他: 接收到的一帧数据
*/
uint8_t *atk_mw8266d_uart_rx_get_frame(void)
{
if (myATCmdRx.sta.finsh == 1)
{
myATCmdRx.buf[myATCmdRx.sta.len] = '\0';
//printf("接收到的数据: %s\r\n", myATCmdRx.buf);
return myATCmdRx.buf;
}
else
{
return NULL;
}
}
/**
* @brief 获取ATK-MW8266D UART接收到的一帧数据的长度
* @param 无
* @retval 0 : 未接收到一帧数据
* 其他: 接收到的一帧数据的长度
*/
uint16_t atk_mw8266d_uart_rx_get_frame_len(void)
{
if (myATCmdRx.sta.finsh == 1)
{
return myATCmdRx.sta.len;
}
else
{
return 0;
}
}
/**
* @brief ATK-MW8266D UART初始化
* @param baudrate: UART通讯波特率
* @retval 无
*/
void atk_mw8266d_uart_init(uint32_t baudrate)
{
g_uart_handle.Instance = ATK_MW8266D_UART_INTERFACE; /* ATK-MW8266D UART */
g_uart_handle.Init.BaudRate = baudrate; /* 波特率 */
g_uart_handle.Init.WordLength = UART_WORDLENGTH_8B; /* 数据位 */
g_uart_handle.Init.StopBits = UART_STOPBITS_1; /* 停止位 */
g_uart_handle.Init.Parity = UART_PARITY_NONE; /* 校验位 */
g_uart_handle.Init.Mode = UART_MODE_TX_RX; /* 收发模式 */
g_uart_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE; /* 无硬件流控 */
g_uart_handle.Init.OverSampling = UART_OVERSAMPLING_16; /* 过采样 */
HAL_UART_Init(&g_uart_handle); /* 使能ATK-MW8266D UART
* HAL_UART_Init()会调用函数HAL_UART_MspInit()
* 该函数定义在文件usart.c中
*/
}
/**
* @brief ATK-MW8266D UART中断回调函数
* @param 无
* @retval 无
*/
void ATK_MW8266D_UART_IRQHandler(void)
{
uint8_t tmp;
if (__HAL_UART_GET_FLAG(&g_uart_handle, UART_FLAG_ORE) != RESET) /* UART接收过载错误中断 */
{
__HAL_UART_CLEAR_OREFLAG(&g_uart_handle); /* 清除接收过载错误中断标志 */
(void)g_uart_handle.Instance->ISR; /* I先读SR寄存器,再读RDR寄存器 */
(void)g_uart_handle.Instance->RDR;
}
if (__HAL_UART_GET_FLAG(&g_uart_handle, UART_FLAG_RXNE) != RESET) /* UART接收中断 */
{
HAL_UART_Receive(&g_uart_handle, &tmp, 1, 1000); /* UART接收数据 */
if (myATCmdRx.sta.len < (ATK_MW8266D_UART_RX_BUF_SIZE - 1)) /* 判断UART接收缓冲是否溢出
* 留出一位给结束符'\0'
*/
{
myATCmdRx.buf[myATCmdRx.sta.len] = tmp; /* 将接收到的数据写入缓冲 */
myATCmdRx.sta.len++; /* 更新接收到的数据长度 */
}
else /* UART接收缓冲溢出 */
{
myATCmdRx.sta.len = 0; /* 覆盖之前收到的数据 */
myATCmdRx.buf[myATCmdRx.sta.len] = tmp; /* 将接收到的数据写入缓冲 */
myATCmdRx.sta.len++; /* 更新接收到的数据长度 */
}
}
if (__HAL_UART_GET_FLAG(&g_uart_handle, UART_FLAG_IDLE) != RESET) /* UART总线空闲中断 */
{
myATCmdRx.sta.finsh = 1; /* 标记帧接收完成 */
__HAL_UART_CLEAR_IDLEFLAG(&g_uart_handle); /* 清除UART总线空闲中断 */
}
}
atk_mw8266d_usart.h
cpp
#ifndef __ATK_MW8266D_UART_H
#define __ATK_MW8266D_UART_H
#include "main.h"
/* 引脚定义 */
#define ATK_MW8266D_UART_TX_GPIO_PORT GPIOB
#define ATK_MW8266D_UART_TX_GPIO_PIN GPIO_PIN_10
#define ATK_MW8266D_UART_TX_GPIO_AF GPIO_AF7_USART2
#define ATK_MW8266D_UART_TX_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0) /* PA口时钟使能 */
#define ATK_MW8266D_UART_RX_GPIO_PORT GPIOB
#define ATK_MW8266D_UART_RX_GPIO_PIN GPIO_PIN_11
#define ATK_MW8266D_UART_RX_GPIO_AF GPIO_AF7_USART2
#define ATK_MW8266D_UART_RX_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0) /* PA口时钟使能 */
#define ATK_MW8266D_UART_INTERFACE USART3
#define ATK_MW8266D_UART_IRQn USART3_IRQn
//#define ATK_MW8266D_UART_IRQHandler USART3_IRQHandler
#define ATK_MW8266D_UART_CLK_ENABLE() do{ __HAL_RCC_USART3_CLK_ENABLE(); }while(0) /* USART3 时钟使能 */
/* UART收发缓冲大小 */
#define ATK_MW8266D_UART_RX_BUF_SIZE 128
#define ATK_MW8266D_UART_TX_BUF_SIZE 64
#define g_uart_handle huart3
typedef struct
{
uint8_t buf[ATK_MW8266D_UART_RX_BUF_SIZE]; /* 帧接收缓冲 */
struct
{
uint16_t len : 15; /* 帧接收长度,sta[14:0] */
uint16_t finsh : 1; /* 帧接收完成标志,sta[15] */
} sta; /* 帧状态信息 */
} g_uart_rx_frame; /* ATK-MW8266D UART接收帧缓冲信息结构体 */
extern g_uart_rx_frame myATCmdRx;
/* 操作函数 */
void atk_mw8266d_uart_printf(char *fmt, ...); /* ATK-MW8266D UART printf */
void atk_mw8266d_uart_rx_restart(void); /* ATK-MW8266D UART重新开始接收数据 */
uint8_t *atk_mw8266d_uart_rx_get_frame(void); /* 获取ATK-MW8266D UART接收到的一帧数据 */
uint16_t atk_mw8266d_uart_rx_get_frame_len(void); /* 获取ATK-MW8266D UART接收到的一帧数据的长度 */
void atk_mw8266d_uart_init(uint32_t baudrate); /* ATK-MW8266D UART初始化 */
void ATK_MW8266D_UART_IRQHandler(void);
#endif
3.1.2 myTask_atk8266D
myTask_atk8266D.c
cpp
#include "myTask_ATK8266D.h"
#include "atk_mw8266d.h"
#include "usart.h"
#include "main.h"
#include "stdio.h"
#include "string.h"
#include "led.h"
#define DEMO_WIFI_SSID "guilin88"
#define DEMO_WIFI_PWD "12345678"
#define DEMO_TCP_SERVER_IP "192.168.96.95"
#define DEMO_TCP_SERVER_PORT "6688"
void myTask_ATK8266D(void)
{
uint8_t ret;
//char ip_buf[16];
/* 初始化ATK-MW8266D */
printf("开始连接AP.......\r\n");
ret = atk_mw8266d_init(115200);
if (ret != 0)
{
printf("ATK-MW8266D init failed!\r\n");
while (1)
{
LED_R_Toggle;
delay_ms(200);
}
}
// printf("正在恢复出厂设置...\r\n");
// while (atk_mw8266d_restore())
// {
// color_debug();
// }
printf("正在进行AT测试...\r\n");
while (atk_mw8266d_at_test())
{
color_debug();
}
// printf("正在设置波特率...\r\n");
// ret = atk_mw8266d_send_at_cmd("AT+UART=115200,8,1,0,0", "OK", 500);
// while (ret != 0)
// {
// color_debug();
// }
printf("正在设置Station模式...\r\n");
while (atk_mw8266d_set_mode(1))
{
color_debug();
}
// printf("正在进行软件复位...\r\n");
// while (atk_mw8266d_sw_reset())
// {
// color_debug();
// }
// printf("关闭回显功能...\r\n");
// while (atk_mw8266d_ate_config(0))
// {
// color_debug();
// }
printf("正在连接WIFI...\r\n");
while (atk_mw8266d_join_ap(DEMO_WIFI_SSID, DEMO_WIFI_PWD))
{
printf("Error to connect tcp server! 2秒后重新连接!\r\n");
color_debug();
}
// printf("获取IP地址中...\r\n");
// while (atk_mw8266d_get_ip(ip_buf))
// {
// color_debug();
// }
// printf("IP: %s\r\n", ip_buf);
/* 连接TCP服务器 */
printf("正在连接TCP服务器...\r\n");
while (atk_mw8266d_connect_tcp_server(DEMO_TCP_SERVER_IP, DEMO_TCP_SERVER_PORT))
{
printf("Error to connect tcp server! 2秒后重新连接!\r\n");
color_debug();
}
/* 进入透传 */
printf("进入透传...\r\n");
while (atk_mw8266d_enter_unvarnished())
{
color_debug();
}
printf("成功进入透传\r\n");
atk_mw8266d_uart_rx_restart(); // 重新开始接收数据
}
myTask_atk8266D.h
cpp
#ifndef _MYTASK_ATK8266D_H
#define _MYTASK_ATK8266D_H
void myTask_ATK8266D(void);
#endif
3.2 GPS模块
3.2.1 ATGM336H
ATGM336H.c
cpp
#include "ATGM336H.h"
#include "main.h"
#include "usart.h"
#include "string.h"
#include "stdio.h"
char rxdatabufer;
u16 point1 = 0;
_SaveData Save_Data;
LatitudeAndLongitude_s g_LatAndLongData =
{
.E_W = 0,
.N_S = 0,
.latitude = 0.0,
.longitude = 0.0
};
// 串口1中断服务程序
// 注意,读取USARTx->SR能避免莫名其妙的错误
char USART_RX_BUF[USART_REC_LEN]; // 接收缓冲,最大USART_REC_LEN个字节.
uint8_t uart_A_RX_Buff;
// 接收状态
// bit15, 接收完成标志
// bit14, 接收到0x0d
// bit13~0, 接收到的有效字节数目
u16 USART_RX_STA=0; // 接收状态标记
void atgm336h_init(void)
{
clrStruct();
HAL_UART_Receive_IT(&huart4, &uart_A_RX_Buff, 1);
}
//GPS中断回调函数,需要放入串口接收中断中
void atgm336h_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == UART4)
{
// printf("%c", uart_A_RX_Buff);
if(uart_A_RX_Buff == '$')
{
point1 = 0;
}
USART_RX_BUF[point1++] = uart_A_RX_Buff;
if(USART_RX_BUF[0] == '$' && USART_RX_BUF[4] == 'M' && USART_RX_BUF[5] == 'C') //确定是否收到"GPRMC/GNRMC"这一帧数据
{
if(uart_A_RX_Buff == '\n')
{
memset(Save_Data.GPS_Buffer, 0, GPS_Buffer_Length); //清空
memcpy(Save_Data.GPS_Buffer, USART_RX_BUF, point1); //保存数据
Save_Data.isGetData = true;
point1 = 0;
memset(USART_RX_BUF, 0, USART_REC_LEN); //清空
}
}
if(point1 >= USART_REC_LEN)
{
point1 = USART_REC_LEN;
}
HAL_UART_Receive_IT(&huart4, &uart_A_RX_Buff, 1);
}
}
u8 Hand(char *a) // 串口命令识别函数
{
if(strstr(USART_RX_BUF, a)!=NULL)
return 1;
else
return 0;
}
void CLR_Buf(void) // 串口缓存清理
{
memset(USART_RX_BUF, 0, USART_REC_LEN); //清空
point1 = 0;
}
void clrStruct(void)
{
Save_Data.isGetData = false;
Save_Data.isParseData = false;
Save_Data.isUsefull = false;
memset(Save_Data.GPS_Buffer, 0, GPS_Buffer_Length); //清空
memset(Save_Data.UTCTime, 0, UTCTime_Length);
memset(Save_Data.latitude, 0, latitude_Length);
memset(Save_Data.N_S, 0, N_S_Length);
memset(Save_Data.longitude, 0, longitude_Length);
memset(Save_Data.E_W, 0, E_W_Length);
}
void errorLog(int num)
{
while (1)
{
printf("ERROR%d\r\n",num);
}
}
void parseGpsBuffer(void)
{
char *subString;
char *subStringNext;
char i = 0;
uint16_t Number=0, Integer=0, Decimal=0;
if (Save_Data.isGetData)
{
Save_Data.isGetData = false;
printf("**************\r\n");
printf("%s\r\n", Save_Data.GPS_Buffer);
for (i = 0 ; i <= 6 ; i++)
{
if (i == 0)
{
if ((subString = strstr(Save_Data.GPS_Buffer, ",")) == NULL)
errorLog(1); //解析错误
}
else
{
subString++;
if ((subStringNext = strstr(subString, ",")) != NULL)
{
char usefullBuffer[2];
switch(i)
{
case 1:memcpy(Save_Data.UTCTime, subString, subStringNext - subString);break; //获取UTC时间
case 2:memcpy(usefullBuffer, subString, subStringNext - subString);break; //获取UTC时间
case 3:memcpy(Save_Data.latitude, subString, subStringNext - subString);break; //获取纬度信息
case 4:memcpy(Save_Data.N_S, subString, subStringNext - subString);break; //获取N/S
case 5:memcpy(Save_Data.longitude, subString, subStringNext - subString);break; //获取经度信息
case 6:memcpy(Save_Data.E_W, subString, subStringNext - subString);break; //获取E/W
default:break;
}
subString = subStringNext;
Save_Data.isParseData = true;
if(usefullBuffer[0] == 'A')
Save_Data.isUsefull = true;
else if(usefullBuffer[0] == 'V')
Save_Data.isUsefull = false;
}
else
{
errorLog(2); //解析错误
}
}
}
if (Save_Data.isParseData)
{
if(Save_Data.isUsefull)
{
// 获取 N/S 和 E/W
g_LatAndLongData.N_S = Save_Data.N_S[0];
g_LatAndLongData.E_W = Save_Data.E_W[0];
// 获取纬度
for(uint8_t i=0; i<9; i++)
{
if(i<2)
{
Number *= 10;
Number += Save_Data.latitude[i]-'0';
}
else if(i<4)
{
Integer *= 10;
Integer += Save_Data.latitude[i]-'0';
}
else if(i==4);
else if(i<9)
{
Decimal *= 10;
Decimal += Save_Data.latitude[i]-'0';
}
}
g_LatAndLongData.latitude = 1.0*Number + (1.0*Integer+1.0*Decimal/10000)/60;
Number = 0;
Integer = 0;
Decimal = 0;
// 获取经度
for(uint8_t i=0; i<10; i++)
{
if(i<3)
{
Number *= 10;
Number += Save_Data.longitude[i]-'0';
}
else if(i<5)
{
Integer *= 10;
Integer += Save_Data.longitude[i]-'0';
}
else if(i==5);
else if(i<10)
{
Decimal *= 10;
Decimal += Save_Data.longitude[i]-'0';
}
}
g_LatAndLongData.longitude = 1.0*Number + (1.0*Integer+1.0*Decimal/10000)/60;
}
}
}
}
void printGpsBuffer(void)
{
if (Save_Data.isParseData)
{
Save_Data.isParseData = false;
printf("Save_Data.UTCTime = %s\r\n", Save_Data.UTCTime);
if(Save_Data.isUsefull)
{
Save_Data.isUsefull = false;
printf("Save_Data.latitude = %s\r\n", Save_Data.latitude);
printf("Save_Data.N_S = %s", Save_Data.N_S);
printf("Save_Data.longitude = %s", Save_Data.longitude);
printf("Save_Data.E_W = %s\r\n", Save_Data.E_W);
printf("latitude: %c,%.4f\r\n", g_LatAndLongData.N_S, g_LatAndLongData.latitude);
printf("longitude: %c,%.4f\r\n", g_LatAndLongData.E_W, g_LatAndLongData.longitude);
}
else
{
printf("GPS DATA is not usefull!\r\n");
}
}
}
ATGM336H.h
cpp
#ifndef __ATGM336H_H
#define __ATGM336H_H
#include "usart.h"
#include "sys.h"
// #include "stdbool.h"
#define USART_REC_LEN 200 // 定义最大接收字节数 200
#define EN_USART1_RX 1 // 使能(1)/禁止(0)串口1接收
#define false 0
#define true 1
// 定义数组长度
#define GPS_Buffer_Length 80
#define UTCTime_Length 11
#define latitude_Length 11
#define N_S_Length 2
#define longitude_Length 12
#define E_W_Length 2
typedef struct SaveData
{
char GPS_Buffer[GPS_Buffer_Length];
char isGetData; // 是否获取到GPS数据
char isParseData; // 是否解析完成
char UTCTime[UTCTime_Length]; // UTC时间
char latitude[latitude_Length]; // 纬度
char N_S[N_S_Length]; // N/S
char longitude[longitude_Length]; // 经度
char E_W[E_W_Length]; // E/W
char isUsefull; // 定位信息是否有效
} _SaveData;
// 经纬度数据
typedef struct _LatitudeAndLongitude_s
{
float latitude; // 纬度
float longitude; // 经度
char N_S; // 北南
char E_W; // 东西
} LatitudeAndLongitude_s;
extern char rxdatabufer;
extern u16 point1;
extern _SaveData Save_Data;
extern LatitudeAndLongitude_s g_LatAndLongData;
void atgm336h_UART_RxCpltCallback(UART_HandleTypeDef *huart);
void atgm336h_init(void); // 初始化
void clrStruct(void); // 清除结构体数据
void parseGpsBuffer(void); // 解包函数
void printGpsBuffer(void); // 打印函数
#endif // __ATGM336H_H
3.2.2 myTask_GPS
myTask_GPS.c
cpp
#include "myTask_GPS.h"
#include "stdio.h"
#include "ATGM336H.h"
void myTask_GPS(void){
atgm336h_init();
while (1){
if (Save_Data.isParseData){
Save_Data.isParseData = false;
if(Save_Data.isUsefull){
Save_Data.isUsefull = false;
printf("latitude: %c,%.4f\r\n", g_LatAndLongData.N_S, g_LatAndLongData.latitude);
printf("longitude: %c,%.4f\r\n", g_LatAndLongData.E_W, g_LatAndLongData.longitude);
}
else{
printf("GPS DATA is not usefull!\r\n");
}
}
HAL_Delay(30);
}
}
3.3 语音模块
直接使用串口2接收指令信息。
3.4 串口重定义
支持printf函数,便于打印调试信息到PC端,适配STM32H7系列。其他系列需要查看不同的芯片手册。
cpp
/******************************************************************************************/
/* 加入以下代码, 支持printf函数, 而不需要选择use MicroLIB */
#if 1
#if (__ARMCC_VERSION >= 6010050) /* 使用AC6编译器时 */
__asm(".global __use_no_semihosting\n\t"); /* 声明不使用半主机模式 */
__asm(".global __ARM_use_no_argv \n\t"); /* AC6下需要声明main函数为无参数格式,否则部分例程可能出现半主机模式 */
#else
/* 使用AC5编译器时, 要在这里定义__FILE 和 不使用半主机模式 */
#pragma import(__use_no_semihosting)
struct __FILE
{
int handle;
/* Whatever you require here. If the only file you are using is */
/* standard output using printf() for debugging, no file handling */
/* is required. */
};
#endif
/* 不使用半主机模式,至少需要重定义_ttywrch\_sys_exit\_sys_command_string函数,以同时兼容AC6和AC5模式 */
int _ttywrch(int ch)
{
ch = ch;
return ch;
}
/* 定义_sys_exit()以避免使用半主机模式 */
void _sys_exit(int x)
{
x = x;
}
char *_sys_command_string(char *cmd, int len)
{
return NULL;
}
/* FILE 在 stdio.h里面定义. */
FILE __stdout;
/* 重定义fputc函数, printf函数最终会通过调用fputc输出字符串到串口 */
int fputc(int ch, FILE *f)
{
while ((USART1->ISR & 0X40) == 0); /* 等待上一个字符发送完成 */
USART1->TDR = (uint8_t)ch; /* 将要发送的字符 ch 写入到DR寄存器 */
return ch;
}
#endif
/***********************************************END*******************************************/