历史上的今天
返回首页

历史上的今天

今天是:2024年10月16日(星期三)

正在发生

2019年10月16日 | PIC单片机模拟异步串行通讯UART

2019-10-16 来源:eefocus

用TMR0实现定时查询。任何带中断的PIC上都可以实现。可用此法扩展多个串口。

;|--------------------------------------------------------------|
;|  Implement duplex USART base on normal I/O pin               |
;|  Using TIMER0 interrupt for bit timing                       |
;|  Tested on PIC16F83 running at 4MHz                          |
;|  Written by Paul Zhang, Microchip Tech Inc                   |
;|  6 Aug, 2000                                                 |
;|  All rights reserved                                         |
;|--------------------------------------------------------------|
    errorlevel    -302    ;no bank warning
    errorlevel    -301    ;no default file warning
    
    list      p=16F83    ;define processor
    #include     ;

    __CONFIG   _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
    ;code protect         =    OFF
    ;watchdog         =    OFF
    ;power-up delay timer     =    ON
    ;oscillator mode     =    XT

;===============================
;define RAM variables
    cblock    0x0c        ;GPR start from 0x0c
w_temp                ;W context saving during interrupt
status_temp            ;STATUS context saving during interrupt
pclath_temp            ;PCLATH context saving during interrupt

USART_F                ;containing flags for USART
RX_BUFF                ;USART received data buffer
TX_BUFF                ;USART transmitting data buffer
RX_SLICE            ;RX bit-timing control
TX_SLICE            ;TX bit-timing control
RX_bcnt                ;RX received bit counting
TX_bcnt                ;TX transmitting bit counting
RX_STA                ;RX STATE-MACHINE controller
TX_STA                ;TX STATE-MACHINE controller
    endc

;===============================
;pre-definition for readability
#define    RX_PIN    PORTA,2        ;assign RX pin
#define    TX_PIN    PORTA,3        ;assign TX pin
#define    TXEN    USART_F,0    ;USART transmit enable
#define    TXBUSY    USART_F,1    ;USRAT transmit is in progress
#define    RXBF    USART_F,2    ;USART receive buff full
#define    RXBUSY    USART_F,3    ;USART receive is in progress
#define    RX_ERR    USART_F,4    ;USART receive error
#define    TX_ERR    USART_F,5    ;USART transmit error

;===============================
;define constant
#define    OSC_FREQ    .4000    ;oscillator frequency in KHz
#define    BAUDRATE    .2400
#define TMR0CONST    .118    ;256-OSC_FREQ*1000/4/(BAUDRATE*3) + 2

;===============================
;for my personal style
#define    skp0    btfsc
#define    skp1    btfss

;**********************************************************************
        ORG     0x000
        clrwdt
          goto    MAIN        ; go to beginning of program


;=======================================
;Interrupt service routine
        ORG     0x004        ; interrupt vector location

        movwf   w_temp        ; save off current W register contents
        movf    STATUS,w    ; move status register into W register
        banksel    status_temp
        movwf    status_temp    ; save off contents of STATUS register
        movf    PCLATH,w
        movwf    pclath_temp    ; save off contents of PCLATH

        banksel    INTCON        ;select bank
        skp0    INTCON,T0IF    ;test for TMR0 interrupt
        goto    tmr0IntStart    ;do TMR0 ISR
        ;here test for any other interrupt source
        goto    int_end

tmr0IntStart                ;TIMER0 interrupt service
        bcf    INTCON,T0IF    ;clear T0IF
        
        ;====== start of RX =======
        movlw    high($)
        movwf    PCLATH        ;set PCLATH before PCL change
        movf    RX_STA,w    ;get the state value for RX
        andlw    0x03        ;for safeguard purpose
        addwf    PCL,f        ;switch to STATE
        goto    rxStartChk    ;check for START bit
        goto    rxReceiveBit    ;receive DATA bit
        goto    rxIdle        ;wait for idle
        goto    rxEnd        ;do nothing
rxStartChk    ;check for START bit
        skp0    RX_PIN        ;test RX pin for START bit
        goto    rxEnd        ;not found
        ;start bit found. do following
        movlw    .8
        movwf    RX_bcnt        ;count for 8 bits incoming data
        movlw    .4
        movwf    RX_SLICE    ;wait 4 time-slice for 1st data bit
        movlw    .1
        movwf    RX_STA        ;switch to STATE 1 for 1st data bit sampling
        goto    rxEnd
rxReceiveBit    ;receive DATA bit
        decfsz    RX_SLICE,f    ;wait of bit timing
        goto    rxEnd
        ;time to sample incoming data bit
        rrf    RX_BUFF,f    ;right shift for new bit space
        bcf    RX_BUFF,7    ;pre-set to 0
        skp0    RX_PIN        ;incoming data bit test
        bsf    RX_BUFF,7    ;set if data bit = 1
        movlw    .3        ;3 slice for data bit timing
        movwf    RX_SLICE    ;bit timing for next data bit
        decfsz    RX_bcnt,f    ;see if 8-bit completed
        goto    rxEnd
        ;bit receive completed, do follwoing
        movlw    .2
        movwf    RX_STA        ;set to STATE 2 for idle waiting
        bsf    RXBF        ;set receive buffer full
        movf    RX_BUFF,w    ;display data on PORTB
        movwf    PORTB
        goto    rxEnd
rxIdle        ;wait for idle
        skp0    RX_PIN        ;try to find STOP bit
        clrf    RX_STA        ;back to STATE 0 for next byte
        goto    rxEnd
        ;====== End of RX =========
rxEnd
        ;====== start of TX =======
        ;do TX, if transmit is engaged
        skp1    TXEN        ;skip if TXEN set, do TX
        goto    tmr0IntEnd    ;not in transmit mode
        movf    TX_SLICE,f    ;see if in bit-timing delay
        skpnz            ;
        goto    txDo        ;bit-timing completed
        decfsz    TX_SLICE,f    ;keep bit-timing delay
        goto    txEnd
txDo
        ;Transmit STATE-MACHINE control
        movlw    high($)
        movwf    PCLATH        ;set PCLATH before PCL change
        movf    TX_STA,w    ;get current state
        andlw    0x03        ;make sure in range
        addwf    PCL,f        ;switch to TX STATE
        goto    txStartBit    ;send START bit
        goto    txDatBit    ;send DATA bit
        goto    txStop        ;send STOP bit
        goto    txIdle        ;set transtim IDLE
txStartBit    ;TX_STA=0, send START bit here
        bsf    TXBUSY        ;set TX busy flag
        movlw    .8
        movwf    TX_bcnt        ;count for 8 bit transmitting
        bcf    TX_PIN        ;start bit
        movlw    .3
        movwf    TX_SLICE    ;set bit timing
        movlw    .1
        movwf    TX_STA        ;set transmit STATE-MACHINE
        goto    txEnd
txDatBit    ;TX_STA=1, send DATA bit here
        ;time for next bit sending
        rrf    TX_BUFF,f    ;rotate bit to C
        skpnc            ;test C
        goto    $+3
        bcf    TX_PIN        ;0 out
        goto    $+2
        bsf    TX_PIN        ;1 out
        movlw    .3
        movwf    TX_SLICE    ;wait 3 time-slices
        decfsz    TX_bcnt,f
        goto    txEnd        ;8 bit serial not end
        movlw    .2
        movwf    TX_STA        ;set transmit STATE-MACHINE
        goto    txEnd
txStop        ;TX_STA=2, send STOP bit here
        bsf    TX_PIN        ;send STOP bit
        movlw    .3
        movwf    TX_SLICE    ;set bit timing
        movlw    .3
        movwf    TX_STA        ;set transmit STATE-MACHINE
        goto    txEnd
txIdle        ;TX_STA=3, reset transmission to IDLE
        bcf    TXBUSY        ;not busy
        bcf    TXEN        ;not in transmission
        clrf    TX_STA        ;reset transmit STATE-MACHINE
        goto    txEnd
        ;====== End of TX =========
txEnd
        ;add more TMR0 related code here
tmr0IntEnd
        movlw    TMR0CONST
        addwf    TMR0,f
        goto    int_end

int_end
        banksel    pclath_temp
        movf    pclath_temp,w    ; retieve copy of PCLATH register
        movwf    PCLATH
        movf    status_temp,w    ; retrieve copy of STATUS register
        movwf    STATUS        ; restore pre-isr STATUS register contents
        swapf   w_temp,f
        swapf   w_temp,w    ; restore pre-isr W register contents
        retfie            ; return from interrupt


;=======================================
;Code wriiten for test purpose
MAIN
        banksel    TRISA        ;select respective bank
        movlw    b'00000100'    ;RA2-input, RA3-output
        movwf    TRISA
        clrf    TRISB
        movlw    b'10001000'    ;TMR0 in timer mode
        movwf    OPTION_REG
        clrf    STATUS        ;make sure in bank 0

        call    USART_INIT

        movlw    TMR0CONST
        movwf    TMR0

        movlw    0xff
        movwf    PORTB

        bsf    INTCON,T0IE
        bsf    INTCON,GIE
        
LOOP                    ;test code
        skp1    RXBF        ;wait for data received
        goto    $-1
        bcf    RXBF        ;clear data flag
        movf    RX_BUFF,w
        movwf    TX_BUFF        ;send back received data
        bsf    TXEN
        skp0    TXEN        ;wait for transmit completion
        goto    $-1
        goto    LOOP        ;



;=======================================
;Initializtion of software USART
USART_INIT
        clrf    USART_F        ;clear all flag bit
        clrf    RX_STA        ;reset STATE MACHINE
        clrf    TX_STA
        bsf    TX_PIN        ;TX is in Idle
        return


        END                     ;

推荐阅读

史海拾趣

DFRobot公司的发展小趣事

在机器人和开源硬件领域取得一定成绩后,DFRobot开始关注教育市场。他们发现,越来越多的学校和教育机构开始引入机器人和编程课程,以培养学生的创新能力和实践能力。于是,DFRobot推出了一系列针对青少年和创客爱好者的教育产品,如机器人套件、3D打印机等,并通过举办各类竞赛和培训活动,吸引更多的学生和教师参与。这一举措不仅拓展了公司的业务领域,也为公司的长期发展奠定了人才基础。

DB Lectro Inc公司的发展小趣事

为了进一步扩大市场份额,DB Lectro Inc积极寻求与国际知名企业的合作。通过与多家国际公司的技术交流和合作,公司成功地将自身的气体检测技术应用于更多领域,如天然气开采、食品饮料生产等。同时,公司还积极参与国际展览和交流活动,展示了其先进的技术和产品,赢得了国际市场的广泛认可。

Displaytech公司的发展小趣事

2008年,Displaytech推出了HDP Power,这是一项创新的电力解决方案,旨在支持公司客户的电力需求。这一举措不仅体现了Displaytech对客户需求的深刻洞察,也展示了公司在电源领域的技术实力。

ACL staticide公司的发展小趣事

随着公司业务的不断发展,Displaytech于1997年在加利福尼亚州圣地亚哥成立了销售办事处,名为SEACOMP。这一举措标志着公司开始向国际市场进军。SEACOMP的成立不仅为公司带来了更多的商业机会,也促进了公司在全球范围内的技术交流与合作。

Calmos Systems Inc公司的发展小趣事

随着国内市场的饱和,Calmos Systems Inc公司开始将目光投向国际市场。公司制定了详细的国际化战略,包括市场调研、产品定位、销售渠道建设等方面。公司派遣专业团队前往海外市场进行考察和交流,了解当地市场需求和文化特点。同时,公司还积极寻求与国际知名企业的合作机会,共同开拓国际市场。在国际化战略的推动下,公司的业务范围不断扩大,国际市场份额逐年提升。

CUI公司的发展小趣事

随着环保意识的逐渐提升,电子行业开始寻求更加环保的CUI材料和生产工艺。一些公司投入大量研发资金,成功开发出低挥发性有机化合物(VOC)含量的CUI涂料,不仅降低了生产过程中的环境污染,还提高了产品的环保性能。

问答坊 | AI 解惑

华为模拟电路

华为模拟电路 经典教材 绝对值得一看…

查看全部问答>

第四届(1999)全国大学生电子设计竞赛获奖作品

本帖最后由 paulhyde 于 2014-9-15 09:34 编辑 第四届(1999)全国大学生电子设计竞赛获奖作品选编  …

查看全部问答>

高速14层板sch和brd文件下载

xilinx的fpga开发板PCB和原理图下载 原理图(Viewdraw): PCB(Allegro 15.x):…

查看全部问答>

全国电子专业人才设计与技能大赛

本帖最后由 paulhyde 于 2014-9-15 09:21 编辑 一、 大赛项目 “天华杯”嵌入式系统设计与开发大赛(专业组) “天华杯”嵌入式系统设计与开发大赛(大学组) “天华杯”单片机设计与开发大赛(大学组) “众友杯”电 ...…

查看全部问答>

基于ARM/Linux的嵌人式设备远程调试模块设计

嵌入式/Linux/ARM/DSP/FPGA......海量资源下载,不断更新, 海科资源 http://www.haike-source.com/ 0 引 言   目前,大多数的工业设备都有专用的调试接口和调试软件,这种方式能有效解决系统现场调试和维护升级的问题,但也有一些弊端。首先, ...…

查看全部问答>

Windows CE 6.0 无法创建 MediaPlayer COM 对象

大家好! 用VB.Net 2008 + CF3.5 开发了一个简单(无播放界面)的mp3/wma/wav播放器,播放程序在WinCE 6.0及Mobile 6.0的机器上使用, 在工程项目中引用了这个wmp.dll COM组件,编译后的程序在Mobile 6.0的机器上运行无问题,播放音乐也一切正常 ...…

查看全部问答>

nandflash的坏块处理

那位有nandflash的坏块处理方法,说下.…

查看全部问答>

H.264解码器的verilog 代码

本人现在正在研究H.264解码器的verilog 代码,源代码是从网上下的qcif分辨率,baseline的解码器,csnd中已经有人上传过,我现在要把解码器改成cif分辨率,把代码修改之后只能解码一部分数据,其他都是不定态,哪位高手也是研究这方面的,能给指点一 ...…

查看全部问答>

高清监控清晰原理

本帖最后由 jameswangsynnex 于 2015-3-3 19:58 编辑 传统的高清监控分为模拟、数字和网络三种类型。模拟监控的前端是模拟摄像机,后端是矩阵。数字监控的前端也是模拟摄像机,后端是DVR。 高清监控清晰原理 对于视频监控而言,图像清晰度无疑是 ...…

查看全部问答>

MAXIM驱动芯片使用心得

        一、充电保护芯片MAX846使用 MAX8 4 6 A的工作原理如下 :  低压差线性稳压器的输 出端 ( VL) 电压始终为 内部基准 电压的 2倍 , 因此 , VL端可跟踪基准电压。同时可为外部负载提供 2 0 mA的 ...…

查看全部问答>