模式选择 : 配置为异步模式Asynchronous
在 Private includes 中引入头文件:
#include
在 USER CODE BEGIN PD 添加下面代码:
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch,FILE *F)
#endif
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
return ch;
}
使用printf输出浮点数:
Project–>Properties–>C/C++ Build–>Settings–>MCU settings,如下图所示,勾选上即可。
/* USER CODE BEGIN Includes */
#include
/* USER CODE END Includes */
/* USER CODE BEGIN PD */
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch,FILE *F)
#endif
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
return ch;
}
/* USER CODE END PD */
/* USER CODE BEGIN 3 */
HAL_Delay(500);
printf("Hello World!\r\n");
}
/* USER CODE END 3 */
/* USER CODE BEGIN Includes */
#include
/* USER CODE END Includes */
/* USER CODE BEGIN PD */
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch,FILE *F)
#endif
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
return ch;
}
/* USER CODE END PD */
/* USER CODE BEGIN PV */
uint8_t RxBuff[1]; // 用来接收串口2发送的数据
/* USER CODE END PV */
/* USER CODE BEGIN 2 */
HAL_UART_Receive_IT(&huart2, RxBuff, 1);
/* USER CODE END 2 */
/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART2) // 判断是由哪个串口触发的中断
{
HAL_UART_Transmit(&huart2,RxBuff,1,100); // 接收到数据马上使用串口2发送出去
HAL_UART_Receive_IT(&huart2,RxBuff,1); // 重新使能串口2接收中断
}
}
/* USER CODE END 4 */
/* USER CODE BEGIN Includes */
#include
#include
/* USER CODE END Includes */
/* USER CODE BEGIN PD */
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch,FILE *F)
#endif
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
return ch;
}
/* USER CODE END PD */
/* USER CODE BEGIN PV */
uint8_t RxBuff[1]; //进入中断接收数据的数组
uint8_t DataBuff[100]; //保存接收到的数据的数组
int RxLine=0; //接收到的数据长度
int Rx_flag=0; //接受到数据标志
/* USER CODE END PV */
/* USER CODE BEGIN 0 */
void printf_usart(void)
{
printf("length=%d\r\n",RxLine);
DataBuff[RxLine] = '\0';
printf("Rxdata:%s\r\n",DataBuff);
memset(DataBuff,0,sizeof(DataBuff)); //清空缓存数组
//memset()作用:可以方便的清空一个结构类型的变量或数组。
//例句:memset(aTxbuffer,0,sizeof(aTxbuffer)) 用memset清空aTxbuffer。
RxLine=0; //清空接收长度
}
/* USER CODE END 0 */
/* USER CODE BEGIN 2 */
HAL_UART_Receive_IT(&huart2, (uint8_t *)RxBuff, 1);
HAL_TIM_Base_Start_IT(&htim3);//开启定时器
/* USER CODE END 2 */
/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART2) // 判断是由哪个串口触发的中�?
{
RxLine++; //每接收到一个数据,进入回调数据长度加1
DataBuff[RxLine-1]=RxBuff[0]; //把每次接收到的数据保存到缓存数组
Rx_flag=1;
if(RxBuff[0]==0xff) //接收结束标志位,这个数据可以自定义,根据实际需求,这里只做示例使用,不一定是0xff
{
printf_usart();
}
RxBuff[0]=0;
HAL_UART_Receive_IT(&huart2, (uint8_t *)RxBuff, 1); //每接收一个数据,就打开一次串口中断接收,否则只会接收一个数据就停止接收
__HAL_TIM_SET_COUNTER(&htim3, 1); // 计数清零,从头开始计
}
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
if (htim->Instance == TIM3){
// 判断是由哪个定时器触发的中断
if(Rx_flag==1)
{
printf_usart();
Rx_flag=0;
}
}
}
/* USER CODE END 4 */
空闲中断是接受数据后出现一个 byte 的高电平 (空闲) 状态, 就会触发空闲中断. 并不是空闲就会一直中断,准确的说应该是上升沿(停止位)后一个 byte,如果一直是低电平是不会触发空闲中断的(会触发 break中断)。所以为了减少误进入串口空闲中断,串口 RX 的 IO 管脚一定设置成 Pull-up<上拉模式>,串口空闲中断只是接收的数据时触发,发送时不触发。
说明白一点,就是我们在发送数据的时候,是一直在发送,不会有一帧这么长的空闲,当发送数据结束后,就会产生空闲中断,所以,可以通过空间中断来判断数据是否接收完成。
相较于上面用定时器实现的方式,这种方法不需要一直产生中断,而占用cpu的资源,也省去了一个定时器。
目前使用DMA和空闲中断的方式,不知道遇到了什么问题,就是看不到现象…参考了很多资料,暂时还没实现,具体错误不知道出在哪里了,找了一天的错误了,快吐了,以后再说吧…