串口通信简介
- 物理层主要就是定义通信接口、电平标准这些东西
- 物理接口是指UART、USB、COM这类物理形式的硬件
-电平标准:根据使用的电平不同,串口通信可以分为TTL标准和RS-232标准
-TTL:理想状态下5V代表逻辑1,0V代表逻辑0
-RS-232:理想状态下-15V代表逻辑1,+15V代表逻辑0 - 协议层
主要规定了数据的格式,数据包由起始位、数据位、校验位以及停止位组成。通信双方的数据包格式必须一致才能正常接发数据。
用STM32CubeMX新建UART
stm32f1配备了3个USART,2个UART;
USART:全称“通用同步异步收发器”;
UART:是阉割版的USART,把同步的功能给去掉了,只能异步通信。
平时用的比较多的是UART。
注意:本工程使用USART1的异步通信功能
1. 新建工程
- File->NewProject
- 芯片选型
3.配置RCC
- 配置USART1
- Connectivity→USART1
- 模式选择:异步,Asynchronous
- 无硬件流控
- 波特率:115200;数据长度:8;奇偶校验位:无(None);停止位:1;数据方向:收发;
- 由于串口需要中断,所以要使能串口中断
5.配置系统时钟
6.配置工程
- 基本配置
- 代码配置
- 生成代码
编辑业务代码
- 自定义一个发送函数
void Usart_Sendstring(uint8_t *str)
{
unsigned int k = 0;
do
{
HAL_UART_Transmit(&huart1, (uint8_t *)(str + k), 1, 1000);
} while (*(str + k) != '\0');
}
- 把C标准库的printf重定向到串口
不同交叉编译链对printf函数的重定向不一样;目前我使用过ARMCC和gcc-arm-eabi这两款编译链;armcc是mdk的编译链,下面分开说。
- 在mdk下的printf函数重定向:只需要重写fputc。
int fputc(int ch, FILE *f)
{
/* 发送一个字节数据到串口DEBUG_USART */
HAL_UART_Transmit(&UartHandle, (uint8_t *)&ch, 1, 1000);
return (ch);
}
- 在arm-gcc下的printf函数重定向:需要重写_write函数。
从STM32Cubemx官方提供的例程来看,需要引入这以下函数以及宏,可以把需要的函数以及宏复制到usart.c文件下边
#ifdef __GNUC__
/* With GCC, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
PUTCHAR_PROTOTYPE
{
/* Place your implementation of fputc here */
/* e.g. write a character to the USART1 and Loop until the end of transmission */
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
//该函数可以在HAL库里找到
//STM32Cube_FW_F1_V1.8.0\ProjectsSTM3210E_EVAL\Examples\UART\UART_Printf\SW4STM32
__attribute__((weak)) int _write(int file, char *ptr, int len)
{
int DataIdx;
for (DataIdx = 0; DataIdx < len; DataIdx++)
{
__io_putchar(*ptr++);
}
return len;
}
- 主函数的代码
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
printf("这是重定向printf的输出\n");
Usart_SendString((uint8_t *)"这是自定义函数输出\n");
HAL_Delay(1000);
}
实验现象
把代码下载到板子上,打开串口调试助手可以看到如下现象