1、配置MX的串口(默认其他配置已完成),这里用的是MDK的RAM编译器
2、底层代码生成(略)
3、打开生成的代码工程添加串口通讯内容(默认其他配置工程已完成)
3.1、建立相关的全局变量
uint8_t aRxBuffer; //接收中断缓冲
uint8_t Uart1_RxBuff[256]; //接收缓冲
uint8_t Uart1_Rx_Cnt = 0; //接收缓冲计数
uint8_t cAlmStr[] = {0xF0,0x00,0x00,0xEE,0x00,0x01};//测试发送数据
uint8_t Uart1_TxBuff[256]; //接收缓冲
unsigned char RxData[10][100];//串口接受数据数组本数组最大允许10个串口,每帧最大100组,每组8位
unsigned char RxEndFlag[10];//串口接受完成标志位
3.2、初始化函数,添加在main函数内,在while(1)循环前
HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);//打开接受中断,接受一个数据然后执行中断回调函数,进入回调函数前系统会自动关闭中断
3.3、可以添加映射函数,可以使用printf和scanf(可以略过)
注意使用映射需要添加头文件“ #include <stdio.h> ”
/**
* 函数功能: 重定向c库函数printf到DEBUG_USARTx
* 输入参数: 无
* 返 回 值: 无
* 说 明:无
*/
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
return ch;
}
/**
* 函数功能: 重定向c库函数getchar,scanf到DEBUG_USARTx
* 输入参数: 无
* 返 回 值: 无
* 说 明:无
*/
int fgetc(FILE *f)
{
uint8_t ch = 0;
HAL_UART_Receive(&huart1, &ch, 1, 0xffff);
return ch;
}
3.4、正常发送函数,发送测试用例
3.4.1、DMA发送串口数据
可以定时调用此函数,此函数使得单片机对应串口发送数据
优点:不占用单片机算力资源
缺点:实时性差,发送会延时,传统的485电路(由单片机决定发送接受时机)比较难判断发送时机
建议使用硬件自动切换电路(补充,可以略过)
HAL_UART_Transmit_DMA(&huart1,cAlmStr,6);//串口DMA模式发送
3.4.2、CPU发送串口数据
可以定时调用此函数,此函数使得单片机对应串口发送数据
优点:实时性好,此函数一运行,单片机立刻发送,传统的485电路可用此函数,在此函数前开启485发送机制,运行此函数后,关闭485发送机制打开接受机制--具体操作,函数代码前加上控制“485RT”为高电平的指令,函数代码后加上控制“485RT”为低电平的指令
缺点:占用一定的CPU内存
HAL_UART_Transmit(&huart1, cAlmStr, 6, 0xffff);
3.5、串口中断接受帧消息
此函数为STM32内部接受中断的回调函数--收到串口信息即执行此函数
帧消息内含有帧头、帧尾、帧长度即可使用,注意接受完后重新开启接收中断
//串口接受中断回掉函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART1)
{
unsigned char DataStart =0xAA;//起始帧 - 帧头
unsigned char DataEnd = 0xFF;//帧尾
unsigned char DataLengthBit = 3;//帧长度位 从0开始计数
static unsigned char StartCheck=0;//找到帧头后,开始检查帧
static unsigned char Rx[100];//记录待检查的帧
static unsigned char j_num;//计数
unsigned char i;
if((aRxBuffer == DataStart)&(StartCheck == 0))//遇到起始帧,且没有开始检查记录
{
StartCheck = 1;//开启检查记录
Rx[0] = aRxBuffer;//记录起始帧
j_num = 1;//刷新记录
}
else if(StartCheck == 1)//没开始检查记录,不许进入
{
Rx[j_num] = aRxBuffer;//记录数据
if(j_num == DataLengthBit) //这一位是数据长度
{
if(Rx[j_num] <= DataLengthBit+2)//检查数据长度是否符合要求
{
StartCheck = 0; //不符合实际数据,结束记录
}
}
else if((j_num > DataLengthBit)&(j_num == Rx[DataLengthBit]-1)) //最后一位结束帧
{
if(Rx[j_num] == DataEnd)//符合数据格式 帧结尾
{
for(i=0;i<=j_num;i++)
{
RxData[0][i] = Rx[i]; //取读接受到的串口数据
}
RxEndFlag[0] = 1; //接受到完整一帧数据标志
}
StartCheck = 0;//数据记录结束,或者被终止
}
j_num++;//帧内判断数据位(16进制)增加
}
HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);//打开接受中断,接受一个数据然后执行中断回调函数
}
}