
int UART_WriteBuf(u8 byCom, u8 pBuf, u16 Len)
{
int i = 0;;
if(Len == 0)
return 0;
switch(byCom)
{
case 1 :
Uart_datasend_len = Len - 1;
Uart_dataj = 1;
memmove(Uart_datasend_buff,pBuf,Len);
USART_ITConfig(USART1, USART_IT_TC, ENABLE);
USART_SendData(USART1, pBuf);
break;
case 2 :
Uart_datasend_len = Len - 1;
Uart_dataj = 1;
memmove(Uart_datasend_buff,pBuf,Len);
USART_ITConfig(USART2, USART_IT_TC, ENABLE);
USART_SendData(USART2, pBuf);
break;
case 3 :
Uart_datasend_len = Len - 1;
Uart_dataj = 1;
memmove(Uart_datasend_buff,pBuf,Len);
USART_SendData(USART3, pBuf);
USART_ITConfig(USART3, USART_IT_TXE, ENABLE);
break;
}
return Len;
}
void USART3_IRQHandler(void)
{
int j = 0;
if(USART_GetITStatus(USART3,USART_IT_RXNE))
{
USART_ClearITPendingBit(USART3,USART_IT_RXNE);
Uart_datarec_buff[Uart_datarec_len] = USART_ReceiveData(USART3);
Uart_datarec_len ++;
if(Uart_datarec_len >= UART_DATA_SIZE) //防止数组越界
Uart_datarec_len = UART_DATA_SIZE - 1;
}
else if(USART_GetITStatus(USART3,USART_IT_TXE))
{
USART_ClearITPendingBit(USART3,USART_IT_TXE);
USART_ClearFlag(USART3,USART_FLAG_TC);
if(Uart_dataj <= Uart_datasend_len)
{
// printf("TC = %d,TXE = %d,FLAG_TC = %d\n\r",USART_GetITStatus(USART3,USART_IT_TC),USART_GetITStatus(USART3,USART_IT_TXE),USART_GetFlagStatus (USART3,USART_FLAG_TC));
USART_SendData(USART3,Uart_datasend_buff[Uart_dataj]);
while(j < 800)
j++;
// printf("interrupt:j = %d,len = %d,buff[%d] = %c,buff = %s\n\n\r",Uart_dataj,Uart_datalen,Uart_dataj,Uart_databuff[Uart_dataj],Uart_databuff);
}
else
USART_ITConfig(USART3, USART_IT_TXE, DISABLE);
Uart_dataj++;
}
}
串口时钟使能,GPIO 时钟使能
2) 串口复位
3) GPIO 端口模式设置
4) 串口参数初始化
5) 开启中断并且初始化 NVIC(如果需要开启中断才需要这个步骤)
6) 使能串口
7) 编写中断处理函数
串口时钟使能。串口是挂载在 APB2 下面的外设,所以使能函数为:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1);
2串口复位。当外设出现异常的时候可以通过复位设置,实现该外设的复位,然后重新配置
这个外设达到让其重新工作的目的。一般在系统刚开始配置外设的时候,都会先执行复位该外
设的 *** 作。复位的是在函数 USART_DeInit()中完成:
void USART_DeInit(USART_TypeDef USARTx);//串口复位
比如我们要复位串口 1,方法为:
USART_DeInit(USART1); //复位串口 1
3串口参数初始化。串口初始化是通过 USART_Init()函数实现的,
void USART_Init(USART_TypeDef USARTx, USART_InitTypeDef USART_InitStruct);
这个函数的第一个入口参数是指定初始化的串口标号,这里选择 USART1。
第二个入口参数是一个 USART_InitTypeDef 类型的结构体指针,这个结构体指针的成员变量用
来设置串口的一些参数。一般的实现格式为:
USART_InitStructureUSART_BaudRate = bound; //一般设置为 9600;
USART_InitStructureUSART_WordLength = USART_WordLength_8b;//字长为 8 位数据格式
USART_InitStructureUSART_StopBits = USART_StopBits_1; //一个停止位
USART_InitStructureUSART_Parity = USART_Parity_No; //无奇偶校验位
USART_InitStructureUSART_HardwareFlowControl
= USART_HardwareFlowControl_None; //无硬件数据流控制
USART_InitStructureUSART_Mode = USART_Mode_Rx | USART_Mode_Tx;
//收发模式
USART_Init(USART1, &USART_InitStructure); //初始化串口
从上面的初始化格式可以看出初始化需要设置的参数为:波特率,字长,停止位,奇偶校验位,
硬件数据流控制,模式(收,发)。我们可以根据需要设置这些参数。
4数据发送与接收。STM32 的发送与接收是通过数据寄存器 USART_DR 来实现的,这是
一个双寄存器,包含了 TDR 和 RDR。当向该寄存器写数据的时候,串口就会自动发送,当收
到数据的时候,也是存在该寄存器内。
STM32 库函数 *** 作 USART_DR 寄存器发送数据的函数是:
void USART_SendData(USART_TypeDef USARTx, uint16_t Data);
通过该函数向串口寄存器 USART_DR 写入一个数据。
STM32 库函数 *** 作 USART_DR 寄存器读取串口接收到的数据的函数是:
uint16_t USART_ReceiveData(USART_TypeDef USARTx);
通过该函数可以读取串口接受到的数据。
5串口状态。串口的状态可以通过状态寄存器 USART_SR 读取。USART_SR 的各位描述如
这里我们关注一下两个位,第 5、6 位 RXNE 和 TC。
RXNE(读数据寄存器非空),当该位被置 1 的时候,就是提示已经有数据被接收到了,并
且可以读出来了。这时候我们要做的就是尽快去读取 USART_DR,通过读 USART_DR 可以将
该位清零,也可以向该位写 0,直接清除。
TC(发送完成),当该位被置位的时候,表示 USART_DR 内的数据已经被发送完成了。如
果设置了这个位的中断,则会产生中断。该位也有两种清零方式:1)读 USART_SR,写
USART_DR。2)直接向该位写 0。
状态寄存器的其他位我们这里就不做过多讲解,大家需要可以查看中文参考手册。
在我们固件库函数里面,读取串口状态的函数是:
FlagStatus USART_GetFlagStatus(USART_TypeDef USARTx, uint16_t USART_FLAG);
这个函数的第二个入口参数非常关键,它是标示我们要查看串口的哪种状态,比如上面讲解的
RXNE(读数据寄存器非空)以及 TC(发送完成)。例如我们要判断读寄存器是否非空(RXNE), ***
作库函数的方法是:
USART_GetFlagStatus(USART1, USART_FLAG_RXNE);
我们要判断发送是否完成(TC), *** 作库函数的方法是:
USART_GetFlagStatus(USART1, USART_FLAG_TC);
这些标识号在 MDK 里面是通过宏定义定义的:
你的串口是通过查询方式来发送数据的,为什么要打开收发收发中断呢?关闭收发中断。
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); //初始化发送中断使能
USART_ITConfig(USART1,USART_IT_TXE,ENABLE); //初始化接收中断使能
改为:
USART_ITConfig(USART1,USART_IT_RXNE,DISABLE); //初始化发送中断使能
USART_ITConfig(USART1,USART_IT_TXE,DISABLE); //初始化接收中断使能
USART是通用(U)同步(S)异步(A)收(R)发(T)器。
STM32F103VGT6上有3个USART和2个UART。
同步与异步的区别是:
通信时是否需要对外提供时钟输出。
官方的usart头文件为:
stm32f10x_usarth
USART有2个结构体:
与USART运行相关:
USART_InitTypeDef
成员有:
// 波特率
USART_BaudRate
// 字长
USART_WordLength
// 停止位
USART_StopBits
// 校验位
USART_Parity
// USART模式
USART_Mode
// 硬件流控制
USART_HardwareFlowControl
与该成员相关的宏定义有:
USART_WordLength
USART_WordLength_8b
USART_WordLength_9b
USART_Stop_Bits
USART_StopBits_1
USART_StopBits_0_5
USART_StopBits_2
USART_StopBits_1_5
USART_Parity
USART_Parity_No
USART_Parity_Even
USART_Parity_Odd
USART_Mode
USART_Mode_Rx
USART_Mode_Tx
USART_Hardware_Flow_Control
USART_HardwareFlowControl_None
USART_HardwareFlowControl_RTS
USART_HardwareFlowControl_CTS
USART_HardwareFlowControl_RTS_CTS
另一个结构体与同步通信相关。
USART_ClockInitTypeDef
成员有:
USART_Clock // 时钟使能控制
USART_CPOL // 时钟极性控制
USART_CPHA // 时钟相位控制
USART_LastBit // 最尾位时钟脉冲控制
该类成员相关的宏定义
USART_Clock
USART_Clock_Disable
USART_Clock_Enable
USART_CPOL
USART_CPOL_Low
USART_CPOL_High
USART_CPHA
USART_CPHA_1Edge
USART_CPHA_2Edge
USART_LastBit
USART_LastBit_Disable
USART_LastBit_Enable
// 使用输入的配置信息USART_InitStruct对于USARTx,进行初始化
USART_Init(USART_TypeDef USARTx,USART_InitTypeDef USART_InitStruct);
// 使能串口接收中断
USART_ITConfig(USART_TypeDef USARTx,uint16_t USART_IT, FunctionalState NewState);
// 使能串口USARTx,NewState=>(ENABLE/DISABLE)
USART_Cmd(USART_TypeDef USARTx, FunctionalState NewState);
// 在 USARTx 中发送数据Data
USART_SendData(USART_TypeDef USARTx, uint16_t Data);
// 确认串口USARTx的一些标志位是 set状态还是reset状态
USART_GetFlagStatus(USART_TypeDef USARTx, uint16_t USART_FLAG);
USART_FLAG有:
USART_FLAG_CTS
USART_FLAG_LBD
USART_FLAG_TXE 数据发送寄存器是否为空
USART_FLAG_TC 数据发送完成标志
USART_FLAG_RXNE 数据接收寄存器是否不为空
USART_FLAG_IDLE
USART_FLAG_ORE
USART_FLAG_NE
USART_FLAG_FE
USART_FLAG_PE
// 类似USART_GetFlagStatus,但是专门用来判断中断时间的状态
USART_GetITStatus(USART_TypeDef USARTx, uint16_t USART_IT);
USART_IT有:
USART_IT_CTS
USART_IT_LBD
USART_IT_TXE
USART_IT_TC
USART_IT_RXNE 数据接收寄存器是否不为空
USART_IT_IDLE
USART_IT_ORE_RX
USART_IT_ORE_ER
USART_IT_NE
USART_IT_FE
USART_IT_PE
// 获取USARTx接收到的数据
USART_ReceiveData(USART_TypeDef USARTx);
如果想使用printf来打印调试信息,则生成项目时候需要如下勾选:
会生成两个文件:
syscallsc和tiny_printfc
修改 syscallsc 中的 _write 函数如下:
并在开头加入:
这样就能使用printf了。
程序中自己编写“bsp_usartc”,“bsp_usarth”,“mainc”这三个文件:
“bsp_usartc”文件如下:
“bsp_usarth”文件如下:
主函数如下:
TrueSTUDIO自带串口通信工具:
由此可见 \r\n 才是真正的回车。
如果你仔细研究USART_Init()函数,你会发现,这程序在配置波特率时会读取RCC有关的寄存器来计算当前CPU实际的工作频率是多少,然后计算参数来实现你需要的波特率——就是说不管你把单片机设置为什么样的工作频率,这函数都能让串口以你要求的波特率工作。当然如果你把原来8M的晶振换掉了,那你就需要修改系统中的一个定义:在文件stm32f10xh中的定义HSE_Value,这参数定义了单片机使用外部晶振或时钟源的频率,一般就是8000000,即使用的8MHz晶振。如果你的STM32用了什么73728、110592或者25MHz晶振时,你就要修改HSE_Value定义的值,这样保证串口通信波特率正确。
TXE由硬件来管理。当 if(USART_GetITStatus(USART1,USART_IT_TXE) != RESET) 时表明:
数据已经从TDR 移送到移位寄存器,数据发送已经开始;TDR 寄存器被清空;下一个数据可以被写进USART_DR 寄存器而不会覆盖先前的数据,如USART_SendData(USART1, Framewaitsndbuf[ptrshowfra][ptrusart1]),如果此时USART 正在发送数据,对USART_DR 寄存器的写 *** 作把数据存进TDR 寄存器,并在当前传输结束时把该数据复制进移位寄存器。如果此时USART 没有在发送数据,处于空闲状态,对USART_DR 寄存器的写 *** 作直接把数据放进移位寄存器,数据传输开始,TXE 位立即被置起。通常串口中断发送用这种方式。
当一帧发送完成时(停止位发送后),TC 位被置起,并且如果USART_CR1 寄存器中的
TCIE 位被置起时,中断产生。先读一下USART_SR 寄存器,再写一下USART_DR 寄存器,可以完成对TC 位的清零。
以上就是关于STM32的串口中断中的变量拿出来用全部的内容,包括:STM32的串口中断中的变量拿出来用、STM32串口通信编程的7大步骤有哪些、STM32外部中断与串口通信不能一起运行,急!等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)