×
嵌入式 > 技术百科 > 详情

模拟串口--基于STM8普通IO口的模拟串口驱动程序

发布时间:2024-05-10 发布时间:
|

标准串口通讯数据的格式为:起始位(1) + 数据位(8) + 校验位(1) + 停止位(1)


串口通讯另外一个重要的的部分是设置波特率,波特率就是1秒钟内串口所传输的Bit(位)数。


关于采样频率:为了较小读取或者发送串行数据的误差,我们采取了在N(我用的是4次)次中断中,取固定位置的读取的数据。


我以stm8中9600波特率计算的过程为例:(1秒钟传输9600位)


可以计算出传输1位所需要的时间 T1 = 1/9600 约为104us


由此可知,发送一位数据,定时器中断的时间间隔应为 104/4 = 26us(4倍采样频率)


stm8 内部晶振频率为16M,我采用8分频也就是2M,故MCU震荡周期为 1/2M = 0.5us


由上面的计算我们可以知道要发送一位数据,定时器中断的初值应设为为 26/0.5 =52


以上为相关数据的计算过程,下面是模拟串口驱动程序和注释:


定时器中断与IO口配置:


void TIM3_Configuration(void)

{

TIM3_DeInit();

TIM3_TimeBaseInit(TIM3_PRESCALER_8,52); //52 104

TIM3_ITConfig(TIM3_IT_UPDATE ,ENABLE);

TIM3_ARRPreloadConfig(ENABLE);

TIM3_Cmd(ENABLE); //DISABLE TIM3_Cmd(DISABLE)

}

//模拟串口引脚定义

#define SIM_UART_TX_PORT GPIOC

#define SIM_UART_TX_PIN GPIO_PIN_2

#define SimUartTxHigh() (SIM_UART_TX_PORT->ODR |= (u8)(SIM_UART_TX_PIN))

#define SimUartTxLow() (SIM_UART_TX_PORT->ODR &= (u8)(~SIM_UART_TX_PIN))

#define SIM_UART_RX_PORT GPIOC

#define SIM_UART_RX_PIN GPIO_PIN_3

#define SimUartRxStatus() (SIM_UART_RX_PORT->IDR & SIM_UART_RX_PIN)

GPIO_Init(SIM_UART_RX_PORT, SIM_UART_RX_PIN,GPIO_MODE_IN_PU_NO_IT);

GPIO_Init(SIM_UART_TX_PORT, SIM_UART_TX_PIN,GPIO_MODE_OUT_PP_LOW_FAST);


/* Includes ------------------------------------------------------------------*/

#include "stm8s.h"

#include "global.h"

//默认采样频率为4倍 一下为16M晶振 8分频 后计数器的装载值

//9600B 104us发送一位 4倍采样频率 故为26us发送一位

#define SIM_BAUDRATE_9600 52

#define SIM_BAUDRATE_4800 104

#define SIM_BAUDRATE_2400 208

/* Private variables ---------------------------------------------------------*/

u8 RxByteIndex; //接收字节索引

u8 RxSampFreq; //采样频率控制 1/4

u8 TxXKCnt = 3; //需要发送数据包的字节数

u8 SimUartRxBuff[10]; //接收数据包缓冲

u8 SimUartTxBuff[10] = {0x55, 0xaa, 0x66};

bool IsSimUartRxFinish;//是否接收完成标志

bool IsSimUartRecv; //模拟串口是否处于接收状态

/* Private functions ---------------------------------------------------------*/

/* Public functions ----------------------------------------------------------*/

void InterruptSimUart(void);

static void Drv_SimUartTxByte(void);

static void Drv_SimUartRxByte(void);

/*******************************************************************************

#Function : InterruptSimUart

#Description : 模拟串口中断调用程序 切换发送与接收

#Parameter : NULL

#Return : NULL

#AuthorAndData : huangzhigang 20141013

*******************************************************************************/

void InterruptSimUart(void)

{

if(IsSimUartRxFinish) //接收完成后立刻发送数据 也可以自己定义什么时候发送数据

{

IsSimUartRxFinish = FALSE;

IsSimUartRecv = FALSE;

}

if(IsSimUartRecv)

{

Drv_SimUartRxByte();

}

else

{

Drv_SimUartTxByte();

}

}

/*******************************************************************************

#Function : Drv_SimUartRxByte

#Description : 模拟串口接收函数

#Parameter : NULL

#Return : NULL

#AuthorAndData : huangzhigang 20141013

*******************************************************************************/

static void Drv_SimUartRxByte(void)

{

static u8 RxBitNum; //接收位计数

static u8 Verify; //校验码

static u8 OverTime; //接收超时计数

static u8 s_u8Rxbuff; //一字节接收缓存

if(SimUartRxStatus())

{

OverTime++;

}

else

{

OverTime = 0;

}

if(OverTime > 44)

{

OverTime = 45;

RxByteIndex = 0;

RxBitNum = 0;

}

if((SimUartRxStatus()) && (RxBitNum == 0))

{

RxSampFreq = 0;

}

else

{

++RxSampFreq;

}

if(RxSampFreq == 1)

{

if(RxBitNum == 0) //低电平,起始位bit0

{

if(!SimUartRxStatus())

{

Verify = 0;

s_u8Rxbuff = 0;

RxBitNum++;

}

}

else if((RxBitNum > 0) && (RxBitNum < 9)) //数据位 bit1~8

{

if(SimUartRxStatus()) //高电平

{

s_u8Rxbuff = s_u8Rxbuff | (0x01 << (RxBitNum -1));

Verify++;

}

RxBitNum++;

}

else if(RxBitNum == 9) //校验位 bit9

{

RxBitNum++;

if(Verify & 0x01)

{

if(SimUartRxStatus()) {RxBitNum = 0;} //奇校验

}

else

{

if(!SimUartRxStatus()) {RxBitNum = 0;}

}

}

else if(RxBitNum == 10) //停止位 bit10

{

if(SimUartRxStatus())

{

RxBitNum = 0;

if(RxByteIndex == 0) //头码1为0X55

{

if(s_u8Rxbuff == 0x55)

{

SimUartRxBuff[RxByteIndex] = s_u8Rxbuff;

RxByteIndex++;

[1] [2]
模拟串口STM8普通IO口驱动程序

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
RFID的电子关锁系统设计与实现