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

标准串口通讯数据的格式为:起始位(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++;

关键字:

模拟串口

STM8

普通IO口

驱动程序

编辑:什么鱼 引用地址:

http://news.eeworld.com.cn/mcu/ic492346.html

本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32中,通过普通IO模拟串口通信,需要自己编写相关的发送和接收函数来实现数据的处理和解析。下面是一个示例代码,可以供你参考: ```c #include "stm32f1xx.h" #define UART_TX GPIO_PIN_9 // 发送引脚 #define UART_RX GPIO_PIN_10 // 接收引脚 #define BAUDRATE 9600 // 波特率 GPIO_InitTypeDef GPIO_InitStruct; void delay_us(uint32_t us) { uint32_t tickstart = HAL_GetTick(); uint32_t wait = us * (SystemCoreClock / 1000000U); while ((HAL_GetTick() - tickstart) < wait) { } } void UART_GPIO_Init(void) { __HAL_RCC_GPIOA_CLK_ENABLE(); // 使能GPIOA时钟 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Pin = UART_TX; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // 配置发送引脚为输出模式 GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pin = UART_RX; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // 配置接收引脚为输入模式 } void UART_SendByte(uint8_t data) { uint8_t i; HAL_GPIO_WritePin(GPIOA, UART_TX, GPIO_PIN_RESET); // 发送起始位 for (i = 0; i < 8; i++) { // 按位发送数据 if (data & 0x01) { HAL_GPIO_WritePin(GPIOA, UART_TX, GPIO_PIN_SET); } else { HAL_GPIO_WritePin(GPIOA, UART_TX, GPIO_PIN_RESET); } data >>= 1; delay_us(1000000 / BAUDRATE); } HAL_GPIO_WritePin(GPIOA, UART_TX, GPIO_PIN_SET); // 发送停止位 delay_us(1000000 / BAUDRATE); } uint8_t UART_ReceiveByte(void) { uint8_t data = 0; uint8_t i; while (HAL_GPIO_ReadPin(GPIOA, UART_RX) == GPIO_PIN_RESET) { // 等待接收起始位 } delay_us(1000000 / BAUDRATE / 2); // 延时半个波特率时钟周期,等待数据位 for (i = 0; i < 8; i++) { // 按位接收数据 data >>= 1; if (HAL_GPIO_ReadPin(GPIOA, UART_RX) == GPIO_PIN_SET) { data |= 0x80; } delay_us(1000000 / BAUDRATE); } while (HAL_GPIO_ReadPin(GPIOA, UART_RX) == GPIO_PIN_SET) { // 等待接收停止位 } return data; } int main(void) { HAL_Init(); UART_GPIO_Init(); // 初始化GPIO while (1) { UART_SendByte(0xAA); // 发送数据 uint8_t data = UART_ReceiveByte(); // 接收数据 } } ``` 在这个示例代码中,我们使用GPIOA的Pin9和Pin10分别模拟串口的发送和接收。在发送数据时,我们将发送引脚拉低,并按照位的顺序依次将数据输出到发送引脚上。在接收数据时,我们轮询接收引脚的电平状态,按照位的顺序将数据接收下来。需要注意的是,由于使用IO模拟串口的收发,在高速通讯时容易出现误码和数据丢失等问题,因此需要充分测试和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值