GPIO 模拟串口发送
根据图 3 可知,空闲时数据线处于高电平状态,由高电平跳变为低电平表示通信开始,因此在有效数据传输前将 PB9 置 0;发送起始位后,根据设置的波特率,延时 104us,利用 for 循环开始发送数据位。需要注意的是,串口由最低位开始发送。数据位发送结束,将引脚置 1,模拟停止位。
void Soft_Usart_TXData(u8 ch)
{
uint8_t i = 0;
GPIO_ResetBit(GPIOB,GPIO_PIN_9);
Delay_us(BaudRate_9600);
for(i = 0; i < 8; i++)
{
if(ch & 0x01)
{
GPIO_SetBit(GPIOB,GPIO_PIN_9);
}
else
{
GPIO_ResetBit(GPIOB,GPIO_PIN_9);
}
Delay_us(BaudRate_9600);
ch = ch >> 1;
}
GPIO_SetBit(GPIOB,GPIO_PIN_9);
Delay_us(BaudRate_9600);
}
void Soft_Usart_Send(u8 *buf,u8 len)
{
uint8_t t;
for(t = 0;t < len;t++)
{
Soft_Usart_TXData(buf[t]);
Delay_ms(1);
}
}
GPIO 中断服务函数
当接收到低电平并且接收位超过或等于停止位时,此时重置接收状态为起始位,使能定时器,开始接收新一帧的数据。若接收状态未达到停止位,表示此时的下降沿由有效数据产生,并不表示新数据的到来,可直接跳出中断。
void EINT15_10_IRQHandler(void)
{
if(EINT_ReadStatusFlag(EINT_LINE_10) != RESET)
{
if(Soft_Usart_RXData() == 0)
{
if(recvState >= COM_STOP_BIT)
{
recvState = COM_START_BIT;
TMR_Enable(TMR4);
flag = 1;
}
}
EINT_ClearStatusFlag(EINT_LINE_10);
}
}
TMR 中断服务函数
开启定时器后,每隔 104us 触发中断。进入中断服务函数,完成数据的按位接收。由于串口发送数据时,由最低位开始发送,在接收一位数据后需通过移位,将其放置在正确的位置,保证接收数据的准确性。当读取到停止位时,将接收值存入缓存区。
void TMR4_IRQHandler(void)
{
if(TMR_ReadStatusFlag(TMR4,TMR_FLAG_UPDATE) != RESET)
{
TMR_ClearStatusFlag(TMR4,TMR_FLAG_UPDATE);
recvState++;
if(recvState >= COM_STOP_BIT)
{
TMR_Disable(TMR4);
USART_buf[len++] = recvData;
return;
}
if(Soft_Usart_RXData())
{
recvData |= (1 << (recvState - 1));
}
else
{
recvData &= ~(1 << (recvState - 1));
}
}
}
主函数
完成初始化后,持续发送接收到的数据。
int main(void)
{
NVIC_ConfigPriorityGroup(NVIC_PRIORITY_GROUP_2);
Delay_Init();
Soft_Usart_Init();
TMR4_Init();
while (1)
{
if(len > 10)
{
len = 0;
Soft_Usart_Send(USART_buf,11);
}
}
}
|