由于项目需要用到很多串口,而STM32F030的串口资源较少,所以需要自己写模拟串口,下面是过程。
首先进行初始化:
#define Auart1RxEXTIPort EXTI_PortSourceGPIOA
#define Auart1RxEXTIPin EXTI_PinSource5
#define Auart1RxLineEXTI_Line5
#define Auart1RCC RCC_AHBPeriph_GPIOA
#define Auart1Port GPIOA
#define Auart1TxPin GPIO_Pin_6
#define Auart1RxPin GPIO_Pin_5
#define Auart1TxLow GPIO_ResetBits(Auart1Port,Auart1TxPin);
#define Auart1TxHigh GPIO_SetBits(Auart1Port,Auart1TxPin);
void Ausart1_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStruct;
NVIC_InitTypeDef NVIC_InitStructure;
RCC->AHBENR |= Auart1RCC;
//TX
GPIO_InitStructure.GPIO_Pin = Auart1TxPin;//
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_Init(Auart1Port, &GPIO_InitStructure);
//RX
GPIO_InitStructure.GPIO_Pin = Auart1RxPin;//
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; // 上拉输入
GPIO_Init(Auart1Port, &GPIO_InitStructure);
RCC->APB2ENR |=RCC_APB2Periph_SYSCFG;
SYSCFG_EXTILineConfig(Auart1RxEXTIPort, Auart1RxEXTIPin);
EXTI_InitStruct.EXTI_Line = Auart1RxLine;
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 = EXTI4_15_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 0x01; //优先级设置比串口1优先 级低,不然会打断串口1接收,导致数据丢失
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
初始化了IO口,包括外部中断和NVIC
然后 写发送函数
void AnalogUart1SendOneByte(uint8_t datatoSend)
{
uint8_t i, tmp;
Auart1TxLow;
Tim14DelayUs(SendingDelay);
for(i = 0; i < 8; i++)
{
tmp= (datatoSend >> i) & 0x01;
if(tmp == 0)
{
Auart1TxLow;
Tim14DelayUs(SendingDelay);//0
}
else
{
Auart1TxHigh;
Tim14DelayUs(SendingDelay);//1
}
}
Auart1TxHigh;
Tim14DelayUs(SendingDelay);
}
其中 Tim14DelayUs()是自己用定时器14做的一个us延时,
TIM14初始化为:
void TIM14_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM14_TimeBaseStructure;
RCC->APB1ENR |= RCC_APB1Periph_TIM14;
TIM14_TimeBaseStructure.TIM_Period = 65535 - 1;
TIM14_TimeBaseStructure.TIM_Prescaler = 48 - 1;
TIM14_TimeBaseStructure.TIM_ClockDivision = 0;
TIM14_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM14, &TIM14_TimeBaseStructure);
TIM_Cmd(TIM14,ENABLE);
}
Tim14DelayUs()函数为
void Tim14DelayUs(__IO uint32_t nTime)
{
uint16_t tmp;
tmp = TIM_GetCounter(TIM14);
if(tmp + nTime <= 65535)
while( (TIM_GetCounter(TIM14) - tmp) < nTime );
else
{
TIM_SetCounter(TIM14, 0);
while( TIM_GetCounter(TIM14) < nTime );
}
}
然后关于参数SendingDelay,是用来控制波特率的参数
计算方法如下
#define BaudRate 9600
#define SendingDelay (1000000/BaudRate)
然后下面函数为发送字符串函数
void AnalogUart1SendString(uint8_t *sData,uint8_t len)
{
uint8_t i=0;
for(i=0;i
{
AnalogUart1SendOneByte(sData[i]);
}
}
然后到最重要的中断服务函数,由于我们采用的是模拟串口,所以我们初始化时将模拟串口的输入IO口配置为中断输入,当有数据过来是,数据下拉串口输入IO,然后出发中断服务函数。下面是中断服务函数
void EXTI4_15_IRQHandler(void)
{
uint8_t i=9;
static uint8_t temp;
if(EXTI_GetITStatus(Auart1RxLine) != RESET)
{
NVIC->ICER[0]= (uint32_t)0x01 << (EXTI4_15_IRQn);//对NVIC_ICER[1]的第7位赋值1
Tim14DelayUs(30);
while(i--)
{
temp >>=1;
if(GPIO_ReadInputDataBit(Auart1Port, Auart1RxPin)) temp |=0x80;
Tim14DelayUs(SendingDelay);
}
if(AUsart1Typedef.RxEn==RX_EN)
{
AUsart1Typedef.RxBuf[AUsart1Typedef.RxBufCount++] = temp;
AUsart1Typedef.RxDelayCount = 0;
AUsart1Typedef.RxNewDataFlag =1;
temp=0;
}
NVIC->ISER[0] = (uint32_t)0x01 << (EXTI4_15_IRQn);
EXTI_ClearITPendingBit(Auart1RxLine);
}
}
标红部分为接受部分,根据自己的需要填入自己的接受数组中就好了。
上一篇:STM32的上拉和下拉电阻
下一篇:关于STM32PB3PB4如何设置成普通GPIO的配置
推荐阅读最新更新时间:2024-03-16 16:15