1、USART和UATR
USART:通用同步/异步串行接收/发送器
UART:通用异步收发传输器
相比于UART可以看出USART多出了同步串行接收/发送功能。
2、配置流程
1) 串口时钟使能,GPIO 时钟使能
2) 串口复位
3) GPIO 端口模式设置
4) 串口参数初始化
5) 开启中断并且初始化 NVIC
6) 使能串口
7) 编写中断处理函数
!注意!:在CT117E平台需使用USART2
串口-管脚-总线映射表:
[tr]串口USART1USART2USART3[/tr]
管脚(TX/RX) | PA9/PA10 | PA2/PA3 | PB10/PB11 |
总线 | APB2 | APB1 | APB1 |
关于硬件流控制:
硬件流:RTS/CTS (Request To Send/Clear To Send)即请求发送/清除发送协议,用于半双工时的收发切换,半双工的意思是说,发的时候不收,收的时候不发。那么怎么区分收发呢?缺省时是DCE向DTE发送数据,当DTE决定向DCE发数据时,先有效RTS,表示DTE希望向DCE发送。一般DCE不能马上转换收发状态,DTE就通过监测CTS是否有效来判断可否发送,这样避免了DTE在DCE未准备好时发送所导致的数据丢失。
简单的说就是:在发送之前告诉你我要发送数据(有效RTS),通过检测CTS来查看这个时候总线是否空闲,来决定是否可以发送数据
在低速场合不用。
3、部分源码
实验目的:实现响应上位机命令(发送字符1):串口发送RTC时间(本次实验是在上次RTC附加闹钟版工程上基础上写的)
main.c:
#include "Headfile.h"
/**
* @file main.c
* @brief 实现响应上位机命令(发送字符1):串口发送RTC时间
* @version 1.1
* @author JosephCooper
* @date 2020年8月27日
*/
void Delay_Ms(u32 nTime);
/** 滴答定时器实现延时中间变量 */
u32 TimingDelay = 0;
/** 闹钟状态标志位 */
u8 AlarmFlag = 0;
/** 闹钟状态标志位 */
u8 USART_StringBuffer[20];
//Main Body
int main(void)
{
u8 Index = 0;
SysTick_Config(SystemCoreClock/1000);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
Delay_Ms(200);
LEDInit();//LED初始化
//关闭所有LED
LEDCmd(Bit_SET);
GPIO_Write(GPIOC,GPIO_ReadOutputData(GPIOC) | 0xFF00);
LEDCmd(Bit_RESET);
STM3210B_LCD_Init();
LCD_Clear(Blue);
LCD_SetBackColor(Blue);
LCD_SetTextColor(White);
USART2_Init(9600);
BuzzerInit();//蜂鸣器初始化
RTCInit(23,59,55);//实时时钟初始化
AlarmEXITInit();
//AlarmSet(23,59,59);
while(1)
{
if(USART_RX_Buffer[0] == '1')
{
RTCtoString(USART_StringBuffer);
USART2_SendString(USART_StringBuffer);
//清空USART接受数据缓冲区
for(Index = 0;Index < 20;Index ++)
{
USART_RX_Buffer[Index] = 0;
}
USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);
}
}
}
//
void Delay_Ms(u32 nTime)
{
TimingDelay = nTime;
while(TimingDelay != 0);
}
USART.c:
#include "Headfile.h"
/** USART接受数据缓冲区 */
u8 USART_RX_Buffer[20];
void USART2_Init(u32 Bound)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
//串口时钟及GPIOA时钟使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
//串口复位
USART_DeInit(USART2);
//GPIO设置 PA2复用推挽输出 PA3浮空
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA,&GPIO_InitStructure);
//串口参数初始化
USART_InitStructure.USART_BaudRate = Bound;//波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//8位字长
USART_InitStructure.USART_StopBits = USART_StopBits_1;//1位停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验
USART_InitStructure.USART_Mode = USART_Mode_Tx|USART_Mode_Rx;//收发双模式
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件流控制
USART_Init(USART2,&USART_InitStructure);
//初始化NVIC
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
USART_Cmd(USART2,ENABLE);//使能串口
USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);//开启USART2接收中断
}
void USART2_SendString(u8 *Str)
{
u8 Index = 0;
while(Str[Index] != 0)
{
USART_SendData(USART2,Str[Index]);
while(USART_GetFlagStatus(USART2,USART_FLAG_TXE) == 0);
Index ++;
}
}
void USART2_IRQHandler(void)
{
u16 Temp;
u8 USART_RX_Cnt = 0;
if(USART_GetFlagStatus(USART2,USART_IT_RXNE) == 1)
{
USART_ClearFlag(USART2,USART_IT_RXNE);
Temp = USART_ReceiveData(USART2);
if(Temp == 'n')
{
USART_RX_Cnt = 0;
USART_ITConfig(USART2,USART_IT_RXNE,DISABLE);
}
else
{
USART_RX_Buffer[USART_RX_Cnt++] = Temp;
}
}
}
RTC.c:(只需要注意RTCtoString函数就行其他同上一节RTC章节中的闹钟部分.c文件相同)
... ...
void RTCtoString(u8 *str)
{
u32 Time = 0;
u8 Hour = 0,Min = 0,Sec = 0;
Time = RTC_GetCounter();
RTC_WaitForLastTask();
if(Time >= (23*3600 + 59*60 + 59))
{
RTC_SetCounter(0);
RTC_WaitForLastTask();
}
Hour = Time / 3600;
Min = (Time % 3600) / 60;
Sec = (Time % 3600) % 60;
sprintf((char *)str,"%.2d:%.2d:%.2dn", Hour, Min, Sec);
}
... ...
注意!:推荐将串口接收中断优先级设为当前所有中断中的最高级。
效果实现图(推荐使用自己熟悉的串口助手调试完成后再使用AccessPort调试):
1、USART和UATR
USART:通用同步/异步串行接收/发送器
UART:通用异步收发传输器
相比于UART可以看出USART多出了同步串行接收/发送功能。
2、配置流程
1) 串口时钟使能,GPIO 时钟使能
2) 串口复位
3) GPIO 端口模式设置
4) 串口参数初始化
5) 开启中断并且初始化 NVIC
6) 使能串口
7) 编写中断处理函数
!注意!:在CT117E平台需使用USART2
串口-管脚-总线映射表:
[tr]串口USART1USART2USART3[/tr]
管脚(TX/RX) | PA9/PA10 | PA2/PA3 | PB10/PB11 |
总线 | APB2 | APB1 | APB1 |
关于硬件流控制:
硬件流:RTS/CTS (Request To Send/Clear To Send)即请求发送/清除发送协议,用于半双工时的收发切换,半双工的意思是说,发的时候不收,收的时候不发。那么怎么区分收发呢?缺省时是DCE向DTE发送数据,当DTE决定向DCE发数据时,先有效RTS,表示DTE希望向DCE发送。一般DCE不能马上转换收发状态,DTE就通过监测CTS是否有效来判断可否发送,这样避免了DTE在DCE未准备好时发送所导致的数据丢失。
简单的说就是:在发送之前告诉你我要发送数据(有效RTS),通过检测CTS来查看这个时候总线是否空闲,来决定是否可以发送数据
在低速场合不用。
3、部分源码
实验目的:实现响应上位机命令(发送字符1):串口发送RTC时间(本次实验是在上次RTC附加闹钟版工程上基础上写的)
main.c:
#include "Headfile.h"
/**
* @file main.c
* @brief 实现响应上位机命令(发送字符1):串口发送RTC时间
* @version 1.1
* @author JosephCooper
* @date 2020年8月27日
*/
void Delay_Ms(u32 nTime);
/** 滴答定时器实现延时中间变量 */
u32 TimingDelay = 0;
/** 闹钟状态标志位 */
u8 AlarmFlag = 0;
/** 闹钟状态标志位 */
u8 USART_StringBuffer[20];
//Main Body
int main(void)
{
u8 Index = 0;
SysTick_Config(SystemCoreClock/1000);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
Delay_Ms(200);
LEDInit();//LED初始化
//关闭所有LED
LEDCmd(Bit_SET);
GPIO_Write(GPIOC,GPIO_ReadOutputData(GPIOC) | 0xFF00);
LEDCmd(Bit_RESET);
STM3210B_LCD_Init();
LCD_Clear(Blue);
LCD_SetBackColor(Blue);
LCD_SetTextColor(White);
USART2_Init(9600);
BuzzerInit();//蜂鸣器初始化
RTCInit(23,59,55);//实时时钟初始化
AlarmEXITInit();
//AlarmSet(23,59,59);
while(1)
{
if(USART_RX_Buffer[0] == '1')
{
RTCtoString(USART_StringBuffer);
USART2_SendString(USART_StringBuffer);
//清空USART接受数据缓冲区
for(Index = 0;Index < 20;Index ++)
{
USART_RX_Buffer[Index] = 0;
}
USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);
}
}
}
//
void Delay_Ms(u32 nTime)
{
TimingDelay = nTime;
while(TimingDelay != 0);
}
USART.c:
#include "Headfile.h"
/** USART接受数据缓冲区 */
u8 USART_RX_Buffer[20];
void USART2_Init(u32 Bound)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
//串口时钟及GPIOA时钟使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
//串口复位
USART_DeInit(USART2);
//GPIO设置 PA2复用推挽输出 PA3浮空
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA,&GPIO_InitStructure);
//串口参数初始化
USART_InitStructure.USART_BaudRate = Bound;//波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//8位字长
USART_InitStructure.USART_StopBits = USART_StopBits_1;//1位停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验
USART_InitStructure.USART_Mode = USART_Mode_Tx|USART_Mode_Rx;//收发双模式
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件流控制
USART_Init(USART2,&USART_InitStructure);
//初始化NVIC
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
USART_Cmd(USART2,ENABLE);//使能串口
USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);//开启USART2接收中断
}
void USART2_SendString(u8 *Str)
{
u8 Index = 0;
while(Str[Index] != 0)
{
USART_SendData(USART2,Str[Index]);
while(USART_GetFlagStatus(USART2,USART_FLAG_TXE) == 0);
Index ++;
}
}
void USART2_IRQHandler(void)
{
u16 Temp;
u8 USART_RX_Cnt = 0;
if(USART_GetFlagStatus(USART2,USART_IT_RXNE) == 1)
{
USART_ClearFlag(USART2,USART_IT_RXNE);
Temp = USART_ReceiveData(USART2);
if(Temp == 'n')
{
USART_RX_Cnt = 0;
USART_ITConfig(USART2,USART_IT_RXNE,DISABLE);
}
else
{
USART_RX_Buffer[USART_RX_Cnt++] = Temp;
}
}
}
RTC.c:(只需要注意RTCtoString函数就行其他同上一节RTC章节中的闹钟部分.c文件相同)
... ...
void RTCtoString(u8 *str)
{
u32 Time = 0;
u8 Hour = 0,Min = 0,Sec = 0;
Time = RTC_GetCounter();
RTC_WaitForLastTask();
if(Time >= (23*3600 + 59*60 + 59))
{
RTC_SetCounter(0);
RTC_WaitForLastTask();
}
Hour = Time / 3600;
Min = (Time % 3600) / 60;
Sec = (Time % 3600) % 60;
sprintf((char *)str,"%.2d:%.2d:%.2dn", Hour, Min, Sec);
}
... ...
注意!:推荐将串口接收中断优先级设为当前所有中断中的最高级。
效果实现图(推荐使用自己熟悉的串口助手调试完成后再使用AccessPort调试):
举报