学习目标:
由于在项目中需要用到多路的串口使用,而自己的单片机目前来讲没法满足我们项目所需要的串口需求,因此要对普通的GPIO进行转换为UART进行使用。从而使得我们单片机能够得到多一路的串口。
学习内容:
1、添加头文件,对编写模拟串口的函数进行梳理
首先我们先添加相应的头文件。既然我们要进行对串口的模拟,因此我们要先了解uart相关的通信协议。由于UART的通信方式是由1个起始位,8个数据位,包含一个奇偶校验位,和结束位构成因此我们将使用单片机中的两个普通的IO口电平的高低进行对相应时序的模拟。
#include "stm32f10x.h"
#include "vuart2.h"
2、宏定义
使用到的io口为
#define OI2_TXD PDout(6)
#define OI2_RXD PDin(7)
#define BuadRate2_9600 104
#define Recive2_Byte 19
u8 len2 = 0;
u8 USART2_buf[Recive2_Byte];
将IO口相应的位带操作函数进行宏定义从而使得在对不同的电平的进行转换的时候更为方便,并且减少了调用其他函数的过程所消耗的时间,程序执行效率更高。
在本次的传输过程中我选用的是使用波特率速率为9600,也就是1s中发送9600个字节,因此对每个字节数据进行计算1000000us/9600可以得出,发一个字节的数据需要进行大概需要 104.16us并且对于相应的电平持续时间要求误差不能超过±5%因此对我们进行时间的控制要求就显得比较重要了。
3、枚举出各个位
enum{
COM_START_BIT,
COM_D0_BIT,
COM_D1_BIT,
COM_D2_BIT,
COM_D3_BIT,
COM_D4_BIT,
COM_D5_BIT,
COM_D6_BIT,
COM_D7_BIT,
COM_STOP_BIT,
};
u8 recvStat2 = COM_STOP_BIT;
u8 recvData2 = 0;
4、IO——TXD进行模拟
void IO2_TXD(u8 Data)
{
u8 i = 0;
OI2_TXD = 0;
delay_us(BuadRate2_9600);
for(i = 0; i < 8; i++)
{
if(Data&0x01)
OI2_TXD = 1;
else
OI2_TXD = 0;
delay_us(BuadRate2_9600);
Data = Data>>1;
}
OI2_TXD = 1;
delay_us(BuadRate2_9600);
}
由于发送的信号是将TXD信号进行拉低处理,因此在拉低TXD相应的IO口之后进行延时处理,再进行循环对我们需要发送的各个位的数据继续进行发送循环发送完成之后将电平拉高代表停止位。
5、构建发送函数
void USART2_Send(u8 *buf, u8 len2)
{
u8 t;
for(t = 0; t < len2; t++)
{
IO2_TXD(buf[t]);
}
}
其中的*buf为需要发送的数据,len2为数据长度,进行循环调用IO_TXD进行一个字节一个字节的数据发送。
6、对使用到的IO口进行初始化
void IO2Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_SetBits(GPIOD,GPIO_Pin_6);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOD, GPIO_PinSource7);
EXTI_InitStruct.EXTI_Line = EXTI_Line7;
EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Falling;
EXTI_InitStruct.EXTI_LineCmd=ENABLE;
EXTI_Init(&EXTI_InitStruct);
NVIC_InitStructure.NVIC_IRQChannel= EXTI9_5_IRQn ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority =2;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
7、使能定时器5
void TIM5_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
TIM_TimeBaseStructure.TIM_Period = arr;
TIM_TimeBaseStructure.TIM_Prescaler =psc;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);
TIM_ClearITPendingBit(TIM5, TIM_FLAG_Update);
TIM_ITConfig(TIM5,TIM_IT_Update,ENABLE );
NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
对TIM5进行初始化操作使得定时器可以检测到各个位的电平持续性时间从而对接收到的数据进行分析。计时结束后进入中断TIM5处理。
8、中断处理函数
void EXTI9_5_IRQHandler(void)
{
if(EXTI_GetFlagStatus(EXTI_Line7) != RESET)
{
if(OI2_RXD == 0)
{
if(recvStat2 == COM_STOP_BIT)
{
recvStat2 = COM_START_BIT;
TIM_Cmd(TIM5, ENABLE);
}
}
EXTI_ClearITPendingBit(EXTI_Line7);
}
}
9、定时器中断处理函数
void TIM5_IRQHandler(void)
{
if(TIM_GetFlagStatus(TIM5, TIM_FLAG_Update) != RESET)
{
TIM_ClearITPendingBit(TIM5, TIM_FLAG_Update);
recvStat2++;
if(recvStat2 == COM_STOP_BIT)
{
TIM_Cmd(TIM5, DISABLE);
USART2_buf[len2++] = recvData2;
if(len2 > Recive2_Byte-1)
{
len2 = 0;
USART2_Send(USART2_buf,Recive2_Byte);
}
return;
}
if(OI2_RXD)
{
recvData2 |= (1 << (recvStat2 - 1));
}else{
recvData2 &= ~(1 << (recvStat2 - 1));
}
}
}
整体代码
vuart2.c
#include "stm32f10x.h"
#include "vuart2.h"
#define OI2_TXD PDout(6)
#define OI2_RXD PDin(7)
#define BuadRate2_9600 104
#define Recive2_Byte 19
u8 len2 = 0;
u8 USART2_buf[Recive2_Byte];
enum{
COM_START_BIT,
COM_D0_BIT,
COM_D1_BIT,
COM_D2_BIT,
COM_D3_BIT,
COM_D4_BIT,
COM_D5_BIT,
COM_D6_BIT,
COM_D7_BIT,
COM_STOP_BIT,
};
u8 recvStat2 = COM_STOP_BIT;
u8 recvData2 = 0;
void IO2_TXD(u8 Data)
{
u8 i = 0;
OI2_TXD = 0;
delay_us(BuadRate2_9600);
for(i = 0; i < 8; i++)
{
if(Data&0x01)
OI2_TXD = 1;
else
OI2_TXD = 0;
delay_us(BuadRate2_9600);
Data = Data>>1;
}
OI2_TXD = 1;
delay_us(BuadRate2_9600);
}
void USART2_Send(u8 *buf, u8 len2)
{
u8 t;
for(t = 0; t < len2; t++)
{
IO2_TXD(buf[t]);
}
}
void IO2Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_SetBits(GPIOD,GPIO_Pin_6);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOD, GPIO_PinSource7);
EXTI_InitStruct.EXTI_Line = EXTI_Line7;
EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Falling;
EXTI_InitStruct.EXTI_LineCmd=ENABLE;
EXTI_Init(&EXTI_InitStruct);
NVIC_InitStructure.NVIC_IRQChannel= EXTI9_5_IRQn ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority =2;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void TIM5_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
TIM_TimeBaseStructure.TIM_Period = arr;
TIM_TimeBaseStructure.TIM_Prescaler =psc;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);
TIM_ClearITPendingBit(TIM5, TIM_FLAG_Update);
TIM_ITConfig(TIM5,TIM_IT_Update,ENABLE );
NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void EXTI9_5_IRQHandler(void)
{
if(EXTI_GetFlagStatus(EXTI_Line7) != RESET)
{
if(OI2_RXD == 0)
{
if(recvStat2 == COM_STOP_BIT)
{
recvStat2 = COM_START_BIT;
TIM_Cmd(TIM5, ENABLE);
}
}
EXTI_ClearITPendingBit(EXTI_Line7);
}
}
void TIM5_IRQHandler(void)
{
if(TIM_GetFlagStatus(TIM5, TIM_FLAG_Update) != RESET)
{
TIM_ClearITPendingBit(TIM5, TIM_FLAG_Update);
recvStat2++;
if(recvStat2 == COM_STOP_BIT)
{
TIM_Cmd(TIM5, DISABLE);
USART2_buf[len2++] = recvData2;
if(len2 > Recive2_Byte-1)
{
len2 = 0;
USART2_Send(USART2_buf,Recive2_Byte);
}
return;
}
if(OI2_RXD)
{
recvData2 |= (1 << (recvStat2 - 1));
}else{
recvData2 &= ~(1 << (recvStat2 - 1));
}
}
}
vuart2.h
#ifndef __VUART2__H
#define __VUART2__H
#include "stm32f10x.h"
void IO2_TXD(u8 Data);
void USART2_Send(u8 *buf, u8 len);
void IO2Config(void);
void TIM5_Int_Init(u16 arr,u16 psc);
#endif
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)