之前其实对于串口在收发字节、收发字符串方面的介绍已经挺完全了,
但今日无意间发现漏了些什么,之前有讲到过串口的printf()发送问题,但也仅仅教大家如何重定向printf();来决定向哪个串口发送数据.
printf();固然是个包容性很强、使用起来很方便的函数,但它却只有一个,无法满足多串口都能享受这么方便的发送方式~
因此我们需要更多类似的函数来满足多个串口更方便发送数据的需要!
此处提供俩种思路:
1.编写普通的串口字节、字符串发送函数
2.自定义类似于printf();发送函数的编写
本文教大家俩种思路的写法,文章提供源码、测试工程下载
目录
相关串口学习文章传送门:
一、普通的串口字节、字符串发送函数编写:
1.编写普通的串口字节、字符串发送函数:
2.自定义printf();发送函数的编写:
整体测试工程下载:
相关串口学习文章传送门:
基础串口收发的知识与配置在此我不做介绍了,没有学习熟悉的可以看下面有关串口的文章,我也许没有全部罗列出来,可以自行去专栏查找~~
MSP432学习笔记10:串口接收字符串命令并执行任务_msp432串口通信_NULL指向我的博客-CSDN博客
MSP432学习笔记3:串口通信初步配置收发_msp432串口_NULL指向我的博客-CSDN博客
需要USB转串口模块(下图绿色盒子 )进行测试,因为除了串口A0其余都不是USB
一、普通的串口字节、字符串发送函数编写:
1.编写普通的串口字节、字符串发送函数:
这个十分简单,无需做过多介绍,此处直接写出实践目标1:
实践目标1:
1.配置初始化串口A1 波特率115200
2.不使用重定向的printf,编写基础的发送函数,使用A1串口发送ABCDEF....给上位机测试
关键代码如下:
//A~I的ascll码值
char str[9]={65,66,67,68,69,70,71,72,73};
//使用A1串口发送8bit的数据
//传入的参数是需要发送的8位的数据
void send_byte_A1(char Data_8bit)
{
UART_transmitData(EUSCI_A1_BASE,Data_8bit);
}
//使用A1串口发送字符串
//传入的参数一个是字符串一个是字符串长度
void send_string_A1(char *str,char numb)
{
char i,j;
i=numb;
for(i=0;i<numb;i++)
{
j=str[i];
UART_transmitData(EUSCI_A1_BASE,j);
}
}
主函数调用情况如下:
#include "main.h"
//A~I的ascll码值
char str[9]={65,66,67,68,69,70,71,72,73};
int main(void)
{
inint_all(); //初始化所有模块
while (1)
{
}
}
//初始化所有模块
void inint_all(void)
{
SysInit(); //时钟配置
delay_init(); //delay_ms函数配置
uart_init(115200); //串口A0初始化
uart_init_A1(115200); //串口A1初始化
// printf("Hello,MSP432!\r\n"); //printf()向串口0打印测试字符
send_string_A1(str,9);
MAP_Interrupt_enableMaster(); // 开启总中断
}
下载测试成功效果图:
介绍总结:
这样编写的基础收发函数固然可用,但需要在进制间与ASCLL码对照转换,十分不方便!
因此,本文后半段推出的自定义printf函数,就很好地解决这个问题!
2.自定义printf();发送函数的编写:
学习自定义格式化输出printf函数的书写,首先要隆重介绍一下库:#include "stdarg.h"
主要目的是为了函数接收可变参数里面含有4个标准宏
#ifdef __clang__
typedef __builtin_va_list va_list;
#define va_start(ap, param) __builtin_va_start(ap, param)
#define va_end(ap) __builtin_va_end(ap)
#define va_arg(ap, type) __builtin_va_arg(ap, type)
#if __STDC_VERSION__ >= 199900L || __cplusplus >= 201103L || !defined(__STRICT_ANSI__)
#define va_copy(dest, src) __builtin_va_copy(dest, src)
#endif
- `va_list`
是一个用于存储可变参数的类型,可以将其理解为一个指向参数列表的指针。
- `va_start(ap, param)`
用于在可变参数函数中初始化 `va_list`,`ap` 是一个 `va_list` 类型的变量,`param` 是函数中最后一个固定参数的名称。
- `va_end(ap)`
用于结束可变参数函数的处理,释放 `va_list` 相关资源。
- `va_arg(ap, type)`
用于获取下一个可变参数的值,`ap` 是一个 `va_list` 类型的变量,`type` 是要获取的参数的类型。
- `va_copy(dest, src)`
用于将 `src` 复制到 `dest`,用于在可变参数函数中进行副本操作。
这些宏的作用是为了在可变参数函数中能够按需获取和操作参数列表的值。
关键代码:
#include "stdarg.h" //别忘记添加这个头文件
#define USART2_TXBUFF_SIZE 25
//自定义printf函数输出
void printf_EUSCI_A1(char *fmt,...)
{
char buffer[USART2_TXBUFF_SIZE]; //USART2_TXBUFF_SIZE为外部定义发送的最大长度
int i = 0;
va_list arg_ptr;
va_start(arg_ptr, fmt); //初始化list
vsnprintf(buffer, USART2_TXBUFF_SIZE+1, fmt, arg_ptr); //将数据返回到buffer
while ((i < USART2_TXBUFF_SIZE) && buffer[i])
{UART_transmitData(EUSCI_A1_BASE,(char)buffer[i++]);}
va_end(arg_ptr);//arg_ptr为空释放内存
}
这个函数可以直接搬运了,想写别的串口的这种函数,全部复制,改名,改串口号即可!
测试成功截图:
我们可以看到:自定义的printf函数(void printf_EUSCI_A1(char *fmt,...))与原汁原味的printf()是一样使用的!~~~
整体测试工程下载:
https://download.csdn.net/download/qq_64257614/88056594?spm=1001.2014.3001.5503
希望对大家有帮助~~~~~