使用USART与计算机通信
电脑上只有usb端口 没有TX 和RX需要一个USB转TTL电平模块来实现通信
芯片C8T6中只有三个UASRT 选其中一个UASRT来通信即可 那么如何定位那个USART的TX 和RX引脚呢?
方式1 查找最小系统板引脚分布图
查找USART1的引脚 RTS CTS是硬件流控 CK引脚是同步时钟 (因为串口用的是异步通信所以不用到) 紫色绿圈圈起来的是复用 当有IO冲突时就可以重映射到别的引脚上
方式2 查找“复用功能重映射表”
当没有被重映射的时候 TX和RX的引脚分别为PA9
PA10 当被重映射后 TX和 RX引脚为PB6 PB7
这次我们使用了重映射
安装USB转TTL驱动
双击打开安装
安装串口调试助手软件
初始化 总开关 发送数据 接收数据 读取标志位
USART_Init
调用这个函数是对 CR寄存器的M STOP PE PS bit位进行操作 M是设置数据帧数据位 STOP是设置停止位的长度 PE是是否使用(使能)校验 PS是使用奇校验还是偶校验
还是声明一个结构体 然后填表对应的值 完成初始化
对应的成员 world…是设置数据帧的数据位的 Parity是设置是否使能校验 是使用奇校验还是偶校验 STopb是设置停止位的长度的 MODE是设置UASRT的模式 是要接收数据还是要发送数据的 (是打开TX
还是RX开关 还是都打开) BaudRate是设置波特率的 Hardwar 是设置硬件流控的
回忆流控的知识点 当数据发送过快时有可能会造成数据的丢失 这时加入一个流控信号 当一个数据传输完成 且接收方接收完成就发送一个流控信号 即可进行下一数据的发送
如图是两个单片机间进行通信 上面的两个单片机左边的只需要使能GTS接收流控信号 而右边的只需要使能RTS发送流控信号 对于下面两个单片机 皆有发送和接收所以需要两个单片机同时使能RTS 和CTS
USART——Cmd (Cmd通常是开关的意思)
这个函数的第一个参数是选择USART的 例如选择USART1就填 USART1 第二个是是否打开总开关
USART_SendData
第一个任然是USART1 第二个就是要发送的数据
USART_GetFlagStatus
如图 第一个为要读取的串口USART1
调用这个函数就可以查询标志位是否为1或0了 如第一个示例代码 就可以判断TXE(SR状态寄存器)是否为1 为1才可以写入新的数据 如果为0就表示还有数据在TDR寄存器中
本次实验不需要用到流控信号(硬件流控)所以不需要RTS CTS引脚 串口通信是异步的也不需要时钟引脚 然后为了增加难度就使用重映射 映射到PB7 PB6
IO引脚初始化
这里直接查表 F1系列的芯片手册
输出是复用(通过USART控制IO引脚)
全双工和半双工的概念 就是全双工就是既可以发送数据也可以接收数据 二者能同时进行 半双工就是当你发送数据的时候就不能接收数据 当你接受数据的时候就不能发送数据 (半双工极少用到)
注意上表的CTS引脚最好为上拉输入 因为当空闲时给CTS一个高电平就默认为空闲模式 当CTS接收到高电平时就TX引脚就不会发送数据 处于空闲状态
RX引脚选择为上拉输入模式
完整的参数表格
复用功能重映射
设置USART的参数
闭合总开关
USART的初始化总代码
#include "stm32f10x.h"
#include "stm32f10x_pal.h"
int main(void)
{
GPIO_InitTypeDef GPIOBInitStruct;
PAL_Init();
//初始化 TX PB6 AF_PP 10MHZ
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能GPIOB的时钟
GPIOBInitStruct.GPIO_Pin = GPIO_Pin_6;
GPIOBInitStruct.GPIO_Mode = GPIO_Mode_AF_PP; //配置PB6为复用推挽输出
GPIOBInitStruct.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOB,&GPIOBInitStruct);// 配置PB6(RTX)为复用推挽模式
//初始化 RX PB7 IPU
GPIOBInitStruct.GPIO_Pin =GPIO_Pin_7;//引脚配置
GPIOBInitStruct.GPIO_Mode = GPIO_Mode_IPU;//配置PB7为输入上拉模式
GPIO_Init(GPIOB,&GPIOBInitStruct);
//重映射USART1的TX RX引脚
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //开启AFIO的时钟
GPIO_PinRemapConfig(GPIO_Remap_USART1,ENABLE);
//使能USART的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
//设置USART1的参数
USART_InitTypeDef USARTInitStruct;
USARTInitStruct.USART_BaudRate = 9600; //设置USART1的波特率为9600
USARTInitStruct.USART_WordLength = USART_WordLength_8b; //设置数据帧的数据位为8位
USARTInitStruct.USART_StopBits = USART_StopBits_1; //设置数据帧的停止位为1位
USARTInitStruct.USART_Parity = USART_Parity_No; //不使用校验位 不需要使能 不使用奇偶校验
USARTInitStruct.USART_Mode = USART_Mode_Rx |USART_Mode_Tx;// 初始化USART1的模式是接收和发送
USARTInitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None ; //不使用硬件流控
USART_Init(USART1,&USARTInitStruct);
//闭合总开关
USART_Cmd(USART1,ENABLE);
while(1)
{
}
}
使用串口来发送数据
实验的简介
串口调试助手参数设置
如何用串口去发送单个字节
左边的代码是对寄存器的直接操作 右边是标准库的库函数操作
发送一个字节的代码
#include "stm32f10x.h"
#include "stm32f10x_pal.h"
int main(void)
{
GPIO_InitTypeDef GPIOBInitStruct;
PAL_Init();
//初始化 TX PB6 AF_PP 10MHZ
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能GPIOB的时钟
GPIOBInitStruct.GPIO_Pin = GPIO_Pin_6;
GPIOBInitStruct.GPIO_Mode = GPIO_Mode_AF_PP; //配置PB6为复用推挽输出
GPIOBInitStruct.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOB,&GPIOBInitStruct);// 配置PB6(RTX)为复用推挽模式
//初始化 RX PB7 IPU
GPIOBInitStruct.GPIO_Pin =GPIO_Pin_7;//引脚配置
GPIOBInitStruct.GPIO_Mode = GPIO_Mode_IPU;//配置PB7为输入上拉模式
GPIO_Init(GPIOB,&GPIOBInitStruct);
//重映射USART1的TX RX引脚
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //开启AFIO的时钟
GPIO_PinRemapConfig(GPIO_Remap_USART1,ENABLE);
//使能USART的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
//设置USART1的参数
USART_InitTypeDef USARTInitStruct;
USARTInitStruct.USART_BaudRate = 9600; //设置USART1的波特率为9600
USARTInitStruct.USART_WordLength = USART_WordLength_8b; //设置数据帧的数据位为8位
USARTInitStruct.USART_StopBits = USART_StopBits_1; //设置数据帧的停止位为1位
USARTInitStruct.USART_Parity = USART_Parity_No; //不使用校验位 不需要使能 不使用奇偶校验
USARTInitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;// 初始化USART1的模式是接收和发送
USARTInitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None ; //不使用硬件流控
USART_Init(USART1,&USARTInitStruct);
//闭合总开关
USART_Cmd(USART1,ENABLE);
//1.等待寄存器TDR清空
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET){}; //TXE为0表示TDR寄存器中仍有数据
// 2.写入要发送的数据
USART_SendData(USART1, 0x5a);
//3/等待数据发送完成
while(USART_GetFlagStatus(USART1,USART_FLAG_TC) == RESET){};
while(1)
{
}
}
发送字节数组
发送一个数组
uint8_t a[] = {0,1,2,3,4,5};
uint32_t i;
for(i=0;i<sizeof(a)/sizeof (uint8_t);i++)
{
//1.等待TXE置位
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET){}; //TXE为0表示TDR寄存器中仍有数据
//2.把数据写入TDR
USART_SendData(USART1, a[i]);
}
//3/等待数据发送完成
while(USART_GetFlagStatus(USART1,USART_FLAG_TC) == RESET){};
发送字符
const char *str = "Hello world";
uint32_t i;
for(i=0; i<strlen(str);i++)
{
// 1. 等待TXE置位
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
// 2. TDR
USART_SendData(USART1, str[i]); } // 3. TC置位
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
串口接收数据
![在这里插入图片描述在这里插入图片描述![](https://img-blog.csdnimg.cn/98551df9699a4894bb7ee5ceef14b001.png)
发送1就灯亮 发送0灯就灭
#include "stm32f10x.h"
#include "stm32f10x_pal.h"
int main(void)
{
GPIO_InitTypeDef GPIOBInitStruct;
PAL_Init();
//初始化 TX PB6 AF_PP 10MHZ
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能GPIOB的时钟
GPIOBInitStruct.GPIO_Pin = GPIO_Pin_6;
GPIOBInitStruct.GPIO_Mode = GPIO_Mode_AF_PP; //配置PB6为复用推挽输出
GPIOBInitStruct.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOB,&GPIOBInitStruct);// 配置PB6(RTX)为复用推挽模式
//初始化 RX PB7 IPU
GPIOBInitStruct.GPIO_Pin =GPIO_Pin_7;//引脚配置
GPIOBInitStruct.GPIO_Mode = GPIO_Mode_IPU;//配置PB7为输入上拉模式
GPIO_Init(GPIOB,&GPIOBInitStruct);
//重映射USART1的TX RX引脚
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //开启AFIO的时钟
GPIO_PinRemapConfig(GPIO_Remap_USART1,ENABLE);
//使能USART的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
//设置USART1的参数
USART_InitTypeDef USARTInitStruct;
USARTInitStruct.USART_BaudRate = 9600; //设置USART1的波特率为9600
USARTInitStruct.USART_WordLength = USART_WordLength_8b; //设置数据帧的数据位为8位
USARTInitStruct.USART_StopBits = USART_StopBits_1; //设置数据帧的停止位为1位
USARTInitStruct.USART_Parity = USART_Parity_No; //不使用校验位 不需要使能 不使用奇偶校验
USARTInitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;// 初始化USART1的模式是接收和发送
USARTInitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None ; //不使用硬件流控
USART_Init(USART1,&USARTInitStruct);
//闭合总开关
USART_Cmd(USART1,ENABLE);
// //1.等待寄存器TDR清空
// while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET){}; //TXE为0表示TDR寄存器中仍有数据
//
// // 2.写入要发送的数据
// USART_SendData(USART1, 0x5a);
//
// //3/等待数据发送完成
// while(USART_GetFlagStatus(USART1,USART_FLAG_TC) == RESET){};
// uint8_t a[] = {0,1,2,3,4,5};
// uint32_t i;
// for(i=0;i
// {
// //1.等待TXE置位
// while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET){}; //TXE为0表示TDR寄存器中仍有数据
// //2.把数据写入TDR
// USART_SendData(USART1, a[i]);
// }
//
// //3/等待数据发送完成
// while(USART_GetFlagStatus(USART1,USART_FLAG_TC) == RESET){};
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIOBInitStruct.GPIO_Pin = GPIO_Pin_13;
GPIOBInitStruct.GPIO_Mode = GPIO_Mode_Out_OD;
GPIOBInitStruct.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOC, &GPIOBInitStruct);
GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_SET); // 熄灭LED
uint8_t c;
while(1)
{
// 1. RXNE
while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);
c = USART_ReceiveData(USART1);
if(c == '0')
{
// 熄灭
GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_SET);
}
else if(c=='1')
{
//点亮
GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_RESET);
}
else
{
}
}
}