STM8S003软件串口的实现

发布者:静默思考最新更新时间:2020-01-22 来源: eefocus关键字:STM8S003  软件串口  发送和接收 手机看文章 扫描二维码
随时随地手机看文章

一切发送和接收的过程都是在后台完成的,具体实现需要一个带捕获&匹配功能的定时器,本实现用的是TIM1。任意具有捕获输入功能的引脚都可以用作接收引脚,任意GPIO引脚都可以用作发送引脚。此实现用TIM_CH4作为发送引脚,TIM1_CH3作为接收引脚。


整个数据传输过程基于定时器1的溢出事件,溢出周期为发送半个bit的时间,这是因为发送和接收用的是同一个定时器。


发送环节:


当有数据字节进入发送缓存后,发送请求标志被置位,最近的一个事件更新中断用于启动此次发送传输,从产生发送请求到开始发送的最长延时为一个溢出周期。在每个偶数的溢出中断中设置相应的发送引脚的电平


接收环节:


空闲状态下,CH3一直处于输入捕获状态,当捕获到第一个下降沿时(起始位),此时计数器的值会自动保存到CCR3中用于之后的匹配,在捕获中断中将通道模式改为匹配,同时禁止该引脚的捕获/匹配功能,使其成为普通的GPIO引脚,以便检测输入电平。由于半个bit周期的溢出事件存在,所以最近的一次匹配肯定出现在起始位的中间点,此时读取引脚上的电平,以得到该位的逻辑,之后丢弃偶数次的匹配中断,在奇数次匹配中断中读取剩余的位的值,知道接收到完整的一字节数据(包括停止位),将通道模式改为捕获,等待下一字节。  


具体实现代码如


#define BAUDRATE_SWUART         (1200)

#define USR_OVF_ONLY            (0x04)

#define TIM1_CR_CEN             (0x01)      //定时器4计数使能

#define TIM1_SR_UIF             (0x01)

#define TIM1_SR_CC3IF           (0x08)

#define UPDATE_INTER_ENABLE     (0x01)

#define CAP_COMP_INTER_ENABLE3  (0x08)

#define CHANN3_INPUT_TI3FP3     (0x01)

#define CHANN3_OUTPUT           (0xFC)

#define CHANN3_FUNC_MASK        (0x03)

#define CHANN3_CAP_COMP_ENABLE  (0x01)

#define CHANN3_CAP_COMP_DISB    (0xFE)

#define CAP_FALL_EDGE           (0x02)

#define START_BIT_POS           (0x01)      //起始位位置

#ifdef  HAVE_PARITY

#define WORD_LENGTH             (11)        //1个起始位,8个数据位,1个奇偶校验位,1个停止位

#define SET_RCV_BIT             (0x400)

#define STOP_BIT_POS            (0x200)     //停止位位置

#define CHECK_BIT_POS           (0x100)

#else

#define WORD_LENGTH             (10)

#define SET_RCV_BIT             (0x200)

#define STOP_BIT_POS            (0x100)

#endif

#define BIT_MASK                (0x01)

#define EVEN_CHECK              (0)

/*

*********************************************************************************************************

*                                            GLOBAL VARIABLES

*********************************************************************************************************

*/

bool      IsFirstBit;

bool      TxByteReady;

bool      IsOdd;

uint8_t   TxBitCnt;                      //发送位数计数

uint8_t   RxBitCnt;

uint16_t  TxByte;                        //移位发送缓存

uint16_t  RxByte;

/*

*********************************************************************************************************

* Description: Swuart初始化

*

* Arguments  : none

*

* Returns    : none

*

* Notes      : 1200

*********************************************************************************************************

*/

void InitSwuart (void)

{

    TIM1->ARRH = (F_MASTER / (BAUDRATE_SWUART * 2)) >> 8;

    TIM1->ARRL = (uint8_t)(F_MASTER / (BAUDRATE_SWUART * 2));

    TIM1->CR1 = USR_OVF_ONLY;                                   //仅计数器溢出才产生更新事件

    TIM1->CCMR3 = CHANN3_INPUT_TI3FP3;

    TIM1->CCER2 = CHANN3_CAP_COMP_ENABLE | CAP_FALL_EDGE;

    TIM1->IER = UPDATE_INTER_ENABLE |CAP_COMP_INTER_ENABLE3;

    TIM1->CR1 = TIM1_CR_CEN;

    SwuartTxByte(0xFF);                                        //初始化后第一个发送的第一个字节要丢弃

}

/*

*********************************************************************************************************

* Description: 发送一个字节

*

* Arguments  : byte: 待发送的字节

*

* Returns    : none

*

* Notes      : none

*********************************************************************************************************

*/

void SwuartTxByte (uint8_t byte)

{  

    TxByte = byte;

    TxBitCnt = WORD_LENGTH;

                       

    TxByte |= STOP_BIT_POS; //添加停止位

                       

    #ifdef HAVE_PARITY

    if (GetParity(byte, EVEN_CHECK)){

        TxByte |= CHECK_BIT_POS;

    }

    #endif

                       

    TxByte = TxByte << START_BIT_POS;      //添加起始位

                       

    TxByteReady = true;

    IsFirstBit = true;

}

/*

*********************************************************************************************************

* Description: 发送数据

*

* Arguments  : data: 指向待发送数据的指针

*              len:  数据长度

*

* Returns    : none

*

* Notes      : none

*********************************************************************************************************

*/

void SwuartSend (const uint8_t *data , uint8_t len)

{

           uint8_t i;

    static uint8_t SwuartSendBuf[50];

                       

    for (i = 0; i < len; i++){

        SwuartSendBuf[i] = data[i];

    }

                       

    i = 0;

    while (len--){

        SwuartTxByte(SwuartSendBuf[i++]);

        while (TxByteReady){

            ;

        }

    }

}

/*

*********************************************************************************************************

* Description: 奇偶校验

*

* Arguments  : byte: 待校验的字节

*              parity: 校验类型选择

*

* Returns    : none

*

* Notes      : 校验位的值

*********************************************************************************************************

*/

#ifdef HAVE_PARITY

uint8_t GetParity (uint8_t byte, uint8_t parity)

{

    uint8_t  i;

    uint8_t  n;

    uint16_t data;

                       

    data = byte;

    n = 0;

                       

    if (data){

        do{

            i = data & 0x01;

            if ( i > 0 ){

                n++;

            }

            data = data >> 1;

        } while ( data > 0 ) ;

    }

    n = n & 0x01;

                       

    if (parity){      //奇校验

        if(n){

            return 0;

        } else {

            return 1;

        }

    } else {         //偶校验

        if(n){

            return 1;

        } else {

            return 0;

        }

    }

}

#endif

#pragma vector = TIM1_OVF_IRQn

__interrupt void Uart_Tx_Timing (void)

{

    static uint8_t OvfInterCnt;

                       

    TIM1->SR1 &= ~TIM1_SR_UIF;

                       

    if (!TxByteReady){

        return;

    }

    if (IsFirstBit){

        OvfInterCnt = 0;

        IsFirstBit = false;

    }

    if (!(OvfInterCnt % 2) && TxBitCnt){          //丢弃奇数此溢出中断,因为发送1位的时间为两个溢出周期

        GPIOC->ODR.ODR4 = TxByte & BIT_MASK;

        TxByte = TxByte >> 1;

        TxBitCnt--;

    }

    OvfInterCnt++;

    if (!TxBitCnt && !(OvfInterCnt % 2)){         //一个字节发送完毕,保证一个完整的停止位

        TxByteReady = false;

    }

}

#pragma vector = TIM1_CAP_COMP_IRQn

__interrupt void Uart_Rx_Timing (void)

{

           uint8_t tmp;

    static uint8_t CapCompCnt;

                       

    TIM1->SR1 &= ~TIM1_SR_CC3IF;

                       

    if ((TIM1->CCMR3 && CHANN3_FUNC_MASK) == CHANN3_INPUT_TI3FP3){

        TIM1->CCER2 &= CHANN3_CAP_COMP_DISB;                //此处顺序不能颠倒,要先禁止,后修改通道模式

        TIM1->CCMR3 &= CHANN3_OUTPUT;

        CapCompCnt = 1;

        RxBitCnt = WORD_LENGTH;

        RxByte = 0;

        return;

[1] [2]
关键字:STM8S003  软件串口  发送和接收 引用地址:STM8S003软件串口的实现

上一篇:stm8 串口模拟接收
下一篇:STM8 模拟串口程序

推荐阅读最新更新时间:2024-11-08 03:04

SRD用的发送接收器IC
    在汽车的RKE(Remote Keyless Entry——远程无键输入)系统和家用装置中都需要大量SRD(Short Range Device——短距离装置)器件。Infineon公司的短距离无线电装置用发送器TDA5100和接收器TDA5200,可普遍用于相应的434和869MHz UHF频段。     迄今为止,SRD优选方案是用分立或半集成技术的SAW稳定系统。这种方案特别是在434MHz频段应用至今。新的高集成度IC技术允许采用更复杂的频率产生技术。HF PLL技术采用晶体谐振器做为频率基准。自动控制振荡器(VCO)固定在此频率基准的倍数上。它所提供的频率稳定度比SAW谐振器好10倍,而且成本更低。
[手机便携]
STM8S003/903 使用ADC中断功能
对使用STM8S003/903这个片子的ADC中断功能(包括两种情况),记录下自己的理解: 一、单通道使用ADC中断的场合: 如果项目中只需要采集一路模拟量,并且想使用中断方式来获取AD值,那么,设置如下: void ADC1_Init(void) { CLK- PCKENR2 |= CLK_PCKENR2_ADC; //ADC Clock Enable ADC1- TDRL = 0x02; //禁用对应AD通道的施密特触发器 ADC1- CR2 &= ~ADC1_CR2_ALIGN;
[单片机]
SRD用的发送接收器IC
    在汽车的RKE(Remote Keyless Entry——远程无键输入)系统和家用装置中都需要大量SRD(Short Range Device——短距离装置)器件。Infineon公司的短距离无线电装置用发送器TDA5100和接收器TDA5200,可普遍用于相应的434和869MHz UHF频段。     迄今为止,SRD优选方案是用分立或半集成技术的SAW稳定系统。这种方案特别是在434MHz频段应用至今。新的高集成度IC技术允许采用更复杂的频率产生技术。HF PLL技术采用晶体谐振器做为频率基准。自动控制振荡器(VCO)固定在此频率基准的倍数上。它所提供的频率稳定度比SAW谐振器好10倍,而且成本更低。
[网络通信]
【STM32Cube_08】使用USART发送接收数据(DMA模式)
本篇文章主要介绍如何使用STM32CubeMX初始化STM32L431RCT6的USART,并使用DMA模式发送数据和接收数据。 1. 准备工作 硬件准备 开发板 首先需要准备一个开发板,这里我准备的是STM32L4的开发板(BearPi): 软件准备 需要安装好Keil - MDK及芯片对应的包,以便编译和下载生成的代码; 准备一个串口调试助手,这里我使用的是Serial Port Utility; 2.生成MDK工程 选择芯片型号 打开STM32CubeMX,打开MCU选择器: 搜索并选中芯片STM32L431RCT6: 配置时钟源 如果选择使用外部高速时钟(HSE),则需要在System
[单片机]
【STM32Cube_08】使用USART<font color='red'>发送</font><font color='red'>和</font><font color='red'>接收</font>数据(DMA模式)
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved