您的当前位置:首页正文

单片机PIC12F1612 数字时钟温度计制作

2023-06-27 来源:好走旅游网
 单片机PIC12F1612时钟温度计 制作 元件包括 实时时钟模块,温度感应器和显示模块OLED OLED SS1306 和 实时时钟模块DS1307 都是用I2C信号线和单片机沟通。另一方面,单片机PIC12F1612和温度感应器DS18B20的通讯则是采用1-wire。PIC的软件里我也加进串行端口(serial port)功能。 单片机PIC12F1612时钟温度计 制作 元件包括 实时时钟模块,温度感应器和显示模块OLED 请参考下面手制电路图,PIC12f1612有6个通用输入输出接口,我用RA0/SCL 和 RA1/SDA脚来与OLED 和 DS1307(实时时钟模块)沟通。RA0(第7脚)做SCL(时钟线),RA1(第6脚)则当SDA(数据线)。在将显示数据传给OLED之前,单片机要做一系列的OLED初始化的程序,详细的步骤请参考下面的程序软件文件。 小型单片机PIC12F1612 是颗8脚迷你单片机,但却是一颗带有杂多功能8位单片机,它有2K的程序内存。封装有PDIP,也有SOIC的。一般应用不用外接晶体来做单片机运行时钟,只接干电池电源3 到5V就可。可网上免费下载 MPLAB IDE 来设PIC12F1612与 温度感应器DS18B20的沟通则是采用1-wire总线技术,DS18B20不需什么初始程序,单片机直接输出一个开始信号,它就回输2个8位的温度数据,DS18B20的资料可从网上取得。我的单片机PIC12F1612软件是用汇编编写的,软件程序使用电脑软件MPLABX来编写,然后需要烧芯器PICKIT3来写入单片机。程序里的一切都使用一般PIC单片机普通功能来写来完成其要求功能,而不用PIC12F1612的自带复杂功能,这样较方便初学者学习。 我在这个制作使用5V的电源,用5V时的平均电流是在14mA左右。这个电路也可以在3V操作。PIC12F1612的程序内存(program memory)有2048位,除了所需的OLED,DS1307和DS18B20的程序外,还剩下一些空位,我也加进串行端口(serial port)功能,RA5是Tx, RA4是Rx, 规格是9600,8N1,可通过TTL/USB转换器与PC链接! 祝学习愉快! 机,一切容易学习上手。 计单片机的软件,再用廉价的烧芯工具将编好的软件烧入单片1 2 3 4 ;********************************************************************** ; This file also serves as a basic code template for Assembly ; language programming on the PIC12F1612. ; ; Refer to the MPASM User's Guide for additional information on ; features of the assembler and linker. ; ; Refer to the respective PIC data sheet for additional ; information on the instruction set. ; ; ;********************************************************************** ;********************************************************************** ; PIC12F1612 8-pin PDIP ; -----uu----- ; +5V/VDD ----| 1 8 |---- VSS/Gnd ; Tx <-- RA5 <---| 2 7 |---> RA0 /ICSPDAT --> SCL/RTC ; Rx <-- RA4 <---| 3 6 |---> RA1 /ICSPCLK --> SDA/RTC ; RA3/MCLR/VPP --->| 4 5 |<--- RA2 /1-wire --> data/DS18B20 ; ------------ ; ; ; PICKIT3 ; ---------- ; ---------------- | > 1|---- MCLR ; | | | 2|---- Vdd (+5V) ; | PC | | 3|---- Vss (Gnd) ; | MPLAB IDE |==================| 4|---- ICSPDAT ; | | | 5|---- ICSPCLK ; | | | 6|---- NC ; ---------------- ---------- ; ; ;********************************************************************** ; ; Filename: 12F1612_OLED_RTC_DS18B20_1.asm ; File Version: 1st version ; Date of change: 2018-3-18 ; ; Author: steven ; Company: ; ; ;********************************************************************** ; ; Files required: P12F1612.INC ; ; ; ;********************************************************************** ; ; Notes: ; RA0 connects to SCL/RTC/OLED, RA1 connects to SDA/RTC/OLED. ; OLED module SS1306 ; RTC model : Tiny RTC module based on DS1307 ; serial port : RA5 as Tx. RA4 as Rx, 9600 8N1 ; RA2 interfaces with DS18B20 by \"One Wire\" communication protoco ; ;********************************************************************** list p=12F1612 ; list directive to define processor #include p12f1612.inc ; processor specific variable definitions expand errorlevel -302 RADIX DEC ; Decimal ;********************************************************************** ; PIC12F1612 Configuration Bit Settings ; Assembly source line config statements ;********************************************************************** ; CONFIG1 ; __config 0xF9DC __CONFIG _CONFIG1, _FOSC_INTOSC & _PWRTE_ON & _MCLRE_ON & _CP_OFF & _BOREN_OFF & _CLKOUTEN_OFF ; CONFIG2 ; __config 0xDEFF __CONFIG _CONFIG2, _WRT_OFF & _ZCD_OFF & _PLLEN_OFF & _STVREN_ON & _BORV_LO & _LPBOR_OFF & _LVP_OFF ; CONFIG3 ; __config 0x612 5 __CONFIG _CONFIG3, _WDTCPS_WDTCPS12 & _WDTE_OFF & _WDTCWS_WDTCWS100 & _WDTCCS_LFINTOSC ;*************************************************************************** ;Variables -- BANK 0 General Purpose Registers 64 Bytes (Address 20h to 6Fh) ;*************************************************************************** CBLOCK 0x20 Delaycount0 Delaycount1 Delaycount2 ;---------OLED module interface variables------------------ count1 ; general bit counter x ; general bit counter y ; general bit counter Offset_low Offset_high Offset1_low Offset1_high Offset2_low Offset2_high temp1 ; general bit counter YY_1 :2 ; YY_1 = high BCD, YY_2 = low BCD, for OLED display \"year\" MM_1 :2 ; MM_1 = high BCD, MM_2 = low BCD, for OLED display \"month\" DD_1 :2 ; DD_1 = high BCD, DD_2 = low BCD, for OLED display \"date\" HR_1 :2 ; HR_1 = high BCD, HR_2 = low BCD, for OLED display \"hours\" MIN_1 :2 ; MIN_1 = high BCD, MIN_2 = low BCD, for OLED display \"minutes\" SECONDS_1 :2 ; SECONDS_1 = high BCD, SECONDS_2 = low BCD, for OLED display \"second\" ACK ; acknowledge bit from OLED Command ; Command byte to be transferred to OLED Dat ; Data byte to be transferred to OLED ;---------DS18B20 interface variables------------------ sign ; sign digit for display hundreds ; hundreds digit for display tens ; tens digit for display ones ; unit digit for display onetenths ; one-tenth digit for display TempLo ; temperature lo byte TempHi ; temperature hi byte flags ; negative or positive temperature value OwByte ; 1-wire byte receive ot transmit temp ;---------DS1307 RTC interface variables------------ SECONDS_byte ; SECONDS Reg content of RTC/DS1307 MIN_byte ; MINUTES Reg content of RTC/DS1307 HR_byte ; HOURS Reg content of RTC/DS1307 DAY_byte ; DAY Reg content of RTC/DS1307SECONDS_BYTE DD_byte ; DATE Reg content of RTC/DS1307SECONDS_BYTE MM_byte ; MONTH Reg content of RTC/DS1307SECONDS_BYTE YY_byte ; YEAR Reg content of RTC/DS1307SECONDS_BYTE ;---------Bin_to_BCD routine variables------------ NUMHI ; Binary HIGH-byte value input to 12-bit binary to BCD conversion routine (Bin_to_BCD routine) NUMLO ; Binary LOW-byte value input to 12-bit binary to BCD conversion routine (Bin_to_BCD routine) D3 ; thousands value output from 12-bit binary to BCD conversion routine (Bin_to_BCD routine) D2 ; hundreds value output from 12-bit binary to BCD conversion routine (Bin_to_BCD routine) D1 ; tens value output from 12-bit binary to BCD conversion routine (Bin_to_BCD routine) D0 ; ones value output from 12-bit binary to BCD conversion routine (Bin_to_BCD routine) ENDC ;----------------------------------------------------------------------------- ;Variables -- All Banks General Purpose Registers 16 Bytes (Address 70h to 7Fh) ;----------------------------------------------------------------------------- CBLOCK 0x70 charTx ; byte to be serial out at SDA/serial port charRx ; byte received at SDA/serial port Delaycount_s ; USED IN SERIAL PORT ROUTINE count ; general bit counter 6 RTC_reg_add ; RTC register address, 0 = seconds reg, 1 = minutes reg, 3 = hours reg, and so on RTC_reg_value ; value to be written into the RTC register selected ENDC ;*************************************************************************** ; VARIABLE/CONSTANT DEFINITIONS ;************************************************************************** d equ 0x0 f equ 0x1 #define SCL TRISA,0 ; TRISA0/pin 7, I2C communication #define SDA TRISA,1 ; TRISA1/pin 6, I2C communication ;---------OLED module interface constants------------ OLED_Address_Wr equ B'01111000' ; OLED slave address (at b7:b1)with WRITE bit (at bit0) OLED_Address_Rd equ B'01111001' ; OLED slave address (at b7:b1) with Read bit (at bit0) OLED_Control_cmd equ B'00000000' ; control byte to indicate the following byte is a command OLED_Control_data equ B'01000000' ; control byte to indicate the following byte is data ;---------DS1307 RTC interface constants------------ RTC_Address_Wr equ B'11010000' ; 0xD1, RTC/DS1307 slave address (at b7:b1) with WRITE bit (at bit0) RTC_Address_Rd equ B'11010001' ; 0xD0, RTC/DS1307 slave address (at b7:b1) with Read bit (at bit0) RTC_Control_Reg equ B'00000111' ; RTC/DS1307 control Reg Address RTC_SECONDS_Reg equ B'00000000' ; RTC/DS1307 SECONDS Reg Address ;---------DS18B20 interface constants------------ #define negflag flags,0 ;*************************************************************************** ; MACRO DEFINITIONS ;*************************************************************************** ; Selects register bank 0 BANK0 MACRO movlb 0 ; select bank 0 ENDM ;---------------------------------------------------------------------- ; Selects register bank 1 BANK1 MACRO movlb 1 ; select bank 1 ENDM ;---------------------------------------------------------------------- ;********************************************************************** ; PROGRAM (Program memory address 0000h to 07FFh, 2K bytes) ;********************************************************************** ORG 0x000 ; processor reset vector goto MAIN ; go to beginning of program ;----------------------------------------------------------------------------- ; Interrupt service routine ;----------------------------------------------------------------------------- ORG 0x004 ; interrupt vector location RETFIE ; return from interrupt ;----------------------------------------------------------------------------- ; MAIN ROUTINE START HERE ;----------------------------------------------------------------------------- ORG 0x006 Table movlw LOW table1 ; get low 8 bits of table1 address, plus 1 addlw 1 addwf Offset_low,d ; do an 8-bit add operation movlw HIGH table1 ; get high 5 bits of address btfsc STATUS,C ; page crossed? addlw 1 ;yes then increment high address addwf Offset_high,d movwf PCLATH ;load high address in latch movfw Offset_low ;load computed offset in w reg ; goto table1 7 ; ORG 0x00f table1 ADDWF PCL,f ; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 dt 0x00,0xe0,0xf0,0x18,0x0c,0x06,0x06,0x06,0x06,0x06,0x06,0x0c,0x18,0xf0,0xe0,0x00 ;0 up dt 0x00,0x07,0x0f,0x18,0x30,0x60,0x60,0x60,0x60,0x60,0x60,0x30,0x18,0x0f,0x07,0x00 ;0 low dt 0x00,0x00,0x00,0x00,0x00,0x08,0x0e,0xfe,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ;1 up dt 0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x7f,0x7f,0x60,0x60,0x00,0x00,0x00,0x00,0x00 ;1 low dt 0x00,0x00,0x00,0x0c,0x0c,0x06,0x06,0x06,0x06,0x86,0xc6,0x6c,0x3c,0x18,0x00,0x00 ;2 dt 0x00,0x00,0x00,0x60,0x70,0x78,0x6c,0x66,0x63,0x61,0x60,0x60,0x60,0x60,0x00,0x00 ;2 dt 0x00,0x00,0x0c,0x0c,0x06,0x06,0x86,0x86,0x86,0x86,0x86,0x86,0xcc,0xfc,0x78,0x00 ;3 dt 0x00,0x00,0x30,0x30,0x60,0x60,0x61,0x61,0x61,0x61,0x61,0x61,0x33,0x3f,0x0e,0x00 ;3 dt 0x00,0x00,0xfc,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xfe,0x00,0x00,0x00,0x00 ;4 dt 0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x7f,0x7f,0x03,0x00,0x00,0x00 ;4 dt 0x00,0x00,0xfe,0xfe,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x86,0x06,0x00 ;5 dt 0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x70,0x39,0x1f,0x0f,0x00 ;5 dt 0x00,0xf0,0xfc,0x8e,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x86,0x0c,0x18,0x00 ;6 dt 0x00,0x0f,0x1f,0x3b,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x3b,0x1f,0x0e,0x00 ;6 ; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 dt 0x00,0x00,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x86,0xc6,0x66,0x3e,0x1c,0x00,0x00 ;7 dt 0x00,0x00,0x40,0x60,0x30,0x18,0x0c,0x06,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00 ;7 dt 0x00,0x30,0xf8,0xcc,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0xcc,0xf8,0x30,0x00 ;8 dt 0x00,0x0c,0x1f,0x33,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x33,0x1f,0x0c,0x00 ;8 dt 0x00,0x78,0xfc,0xce,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0xcc,0xfc,0x78,0x00 ;9 dt 0x00,0x00,0x60,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x73,0x3f,0x1f,0x00 ;9 dt 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ;. decimal point (10) dt 0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x38,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ;. decimal point (10) dt 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ;- negative (11) dt 0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00 ;- negative (11) dt 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ;\" \" positive (12) dt 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ;\" \" positive (12) dt 0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x1c,0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x00 ;\":\" (13) dt 0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x38,0x38,0x38,0x00,0x00,0x00,0x00,0x00,0x00 ;\":\" (13) dt 0x00,0x0e,0x0a,0x0e,0x00,0xe0,0xf8,0x1c,0x0e,0x06,0x06,0x06,0x0c,0x1c,0x18,0x00 ;degreeC (14) dt 0x00,0x00,0x00,0x00,0x00,0x07,0x1f,0x38,0x70,0x60,0x60,0x60,0x30,0x38,0x18,0x00 ;degreeC (14) ; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ; dt 0x00,0x38,0x7c,0xc6,0xc6,0xc6,0x7c,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ;degree sign (14) ; dt 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ;degree sign (14) MAIN Call longdelay_routine2 ; power-up short delay Call MCU_INIT Call OLED_Init Call RTC_INIT ; Initialize RTC/DS1307 ; call Serial_port_check ;------------------------------------------------------------- ; call RTC_timedate_setting ;------------------------------------------------------------- Main_loop ; goto Display_temp Call Gettemperature ; get temperature data from DS18B20 Call RTC_read_timedate ; get real time from DS1307 ; movlw 0x33 ; movwf charTx ; Call serial_out ; movfw YY_byte ; movwf charTx ; Call serial_out 8 ; movfw MM_byte ; movwf charTx ; Call serial_out ; movfw DD_byte ; movwf charTx ; Call serial_out ; movfw DAY_byte ; movwf charTx ; Call serial_out ; movfw HR_byte ; movwf charTx ; Call serial_out ; movfw MIN_byte ; movwf charTx ; Call serial_out ; movfw SECONDS_byte ; movwf charTx ; Call serial_out ;--------------------------------------- ; display date on OLED ;-------------------------------------- movlw 0 ; display '1' at 3,8*0 movwf y movlw 8*0 movwf x ; movlw 1 swapf YY_byte,d ; Swap Nibbles and result in W andlw 0x0F ; mask off high nibble call OLED_Display_value movlw 0 ; display '8' at 3,8*2 movwf y movlw 8*2 movwf x ; movlw 8 movlw 0x0F andwf YY_byte,d call OLED_Display_value movlw 0 ; display '-' at 3,8*4 movwf y movlw 8*4 movwf x movlw 11 call OLED_Display_value movlw 0 ; display '1' at 3,8*6 movwf y movlw 8*6 movwf x ; movlw 1 swapf MM_byte,d ; Swap Nibbles and result in W andlw 0x0F ; mask off high nibble call OLED_Display_value movlw 0 ; display '2' at 3,8*8 movwf y movlw 8*8 movwf x movlw 2 movlw 0x0F andwf MM_byte,d call OLED_Display_value movlw 0 ; display '-' at 3,8*10 movwf y movlw 8*10 movwf x movlw 11 call OLED_Display_value 9 movlw 0 ; display '0' at 3,8*12 movwf y movlw 8*12 movwf x ; movlw 0 swapf DD_byte,d ; Swap Nibbles and result in W andlw 0x0F ; mask off high nibble call OLED_Display_value movlw 0 ; display '2' at 3,8*14 movwf y movlw 8*14 movwf x ; movlw 8 movlw 0x0F andwf DD_byte,d call OLED_Display_value ;--------------------------------------- ; display time on OLED ;-------------------------------------- movlw 3 ; display '1' at 2,8*0 movwf y movlw 8*0 movwf x ; movlw 1 ; for debugging swapf HR_byte,d ; Swap Nibbles and result in W andlw 0x0F ; mask off high nibble call OLED_Display_value movlw 3 ; display '8' at 3,8*2 movwf y movlw 8*2 movwf x ; movlw 8 ; for debugging movlw 0x0F andwf HR_byte,d call OLED_Display_value movlw 3 ; display ':' at 3,8*4 movwf y movlw 8*4 movwf x movlw 13 call OLED_Display_value movlw 3 ; display '1' at 3,8*6 movwf y movlw 8*6 movwf x ; movlw 1 ; for debugging swapf MIN_byte,d ; Swap Nibbles and result in W andlw 0x0F ; mask off high nibble call OLED_Display_value movlw 3 ; display '2' at 3,8*8 movwf y movlw 8*8 movwf x movlw 2 movlw 0x0F andwf MIN_byte,d call OLED_Display_value movlw 3 ; display ':' at 3,8*10 movwf y movlw 8*10 movwf x movlw 13 call OLED_Display_value movlw 3 ; display '0' at 3,8*12 movwf y movlw 8*12 movwf x ; movlw 0 ; for debugging swapf SECONDS_byte,d ; Swap Nibbles and result in W andlw 0x0F ; mask off high nibble 10 call OLED_Display_value movlw 3 ; display '2' at 3,8*14 movwf y movlw 8*14 movwf x ; movlw 8 ; for debugging movlw 0x0F andwf SECONDS_byte,d call OLED_Display_value ;-------------------------------------- ; display temperature on OLED ;-------------------------------------- Display_temp ; Call Gettemperature ; get temperature data from DS18B20 ; movfw sign ; movwf charTx ; Call serial_out ; movfw hundreds ; movwf charTx ; Call serial_out ; movfw tens ; movwf charTx ; Call serial_out ; movfw ones ; movwf charTx ; Call serial_out ; movfw onetenths ; movwf charTx ; Call serial_out movlw 6 ; display at 3,8*12 movwf y movlw 8*2 movwf x ; movlw 0 ; for debugging movfw sign call OLED_Display_value movlw 6 ; display at 3,8*14 movwf y movlw 8*4 movwf x ; movlw 3 ; for debugging movfw hundreds call OLED_Display_value movlw 6 ; display at 3,8*14 movwf y movlw 8*6 movwf x ; movlw 8 ; for debugging movfw tens call OLED_Display_value movlw 6 ; display at 3,8*14 movwf y movlw 8*8 movwf x ; movlw 9 ; for debugging movfw ones call OLED_Display_value movlw 6 ; display '.' at 3,8*14 movwf y movlw 8*10 movwf x movlw 10 ; call OLED_Display_value 11 movlw 6 ; display at 3,8*14 movwf y movlw 8*12 movwf x ; movlw 3 movfw onetenths ; call OLED_Display_value movlw 6 ; display 'degreeC' at 6,8*14 movwf y movlw 8*14 movwf x movlw 14 ; for debugging call OLED_Display_value loop1 ; call longdelay_routine2 ; call longdelay_routine2 ; call longdelay_routine2 goto Main_loop ;******************************************************* ; Basic I2C Communication routines for OLED and DS1307 ;******************************************************* I2C_START_Bit BANK1 bsf SDA ; SDA=1 bsf SCL ; SCL=1 CALL Delay_10us bcf SDA ; SDA=0 CALL Delay_10us bcf SCL ; SCL=0 CALL Delay_10us BANK0 return ;----------------------- I2C_STOP_Bit BANK1 bsf SCL ; SCL=1 CALL Delay_10us bsf SDA ; SDA=1 CALL Delay_10us BANK0 return ;----------------------- I2C_WrByte BANK1 movwf charTx movlw 8 ; initialise counter value, 8-bit movwf count I2C_WrByte2 RLF charTx,f ; C<---b7 bsf SDA ; assume bit7 is high and set SDA line to high first BTFSC STATUS,C; goto $+2 ; if b7==1, set SDA line high by external pull up resistor bcf SDA ; if b7==0, clear SDA nop bsf SCL ; SCL=1 CALL Delay_10us bcf SCL ; SCL=0 CALL Delay_10us decfsz count,f ; decrerement counter, skip if zero goto I2C_WrByte2 ; bcf SDA ; clear SDA BANK0 return ;---------------------- 12 I2C_RdByte BANK1 clrf charRx movlw 8 ; initialise counter value, 8-bit movwf count I2C_RdByte2 bsf SDA ; SDA=1, release SDA line nop bsf SCL ; SCI=1 nop nop nop nop BANK0 movfw PORTA andlw b'00000010' ; receive 1 bit thru SDA/RA1, b7 first movwf temp RRF temp,f ; Rotate Right f through Carry, x2 times RRF temp,f RLF charRx,f ; Rotate Left f through Carry, BANK1 nop bcf SCL ; SCL=0 nop nop nop decfsz count,f goto I2C_RdByte2+1 ; to receive next bit ; bcf SDA ; set SDA pin as output again, and make SDA low (LATA.LATA1 bit is always kept at low) BANK0 return ;----------------------- I2C_WrACK ; send acknowledge bit to SLAVE BANK1 bcf SCL ; SCL=0 nop nop nop bcf SDA ; SDA=0 nop nop nop nop bsf SCL ; SCL=1 NOP NOP NOP NOP bcf SCL ; SCL=0 BsF SDA ; SDA=1, remain low nop nop nop BANK0 return ;----------------------- I2C_RdACK BANK1 bsf SDA ; set SDA pin as input (high impredance), allows OLED to take over the control of the line nop bsf SCL ; SCI goes high nop nop BANK0 movfw PORTA andlw b'000010'; check if ACK bit received movwf ACK ; store at ACK BANK1 nop bcf SCL ; SCL=0 nop nop nop bcf SDA ; SDA=0 13 BANK0 return ;----------------------- I2C_WrCmd call I2C_START_Bit ; movlw OLED_Address_Wr call I2C_WrByte call I2C_RdACK movlw OLED_Control_cmd call I2C_WrByte call I2C_RdACK movfw Command call I2C_WrByte call I2C_RdACK Call I2C_STOP_Bit return ;----------------------- I2C_WrData call I2C_START_Bit ; movlw OLED_Address_Wr call I2C_WrByte call I2C_RdACK movlw OLED_Control_data call I2C_WrByte call I2C_RdACK movfw Dat call I2C_WrByte call I2C_RdACK Call I2C_STOP_Bit return ;******************************************************* ; I2C routines for OLED functions ;******************************************************* Set_Display_On movlw 0xAF ; Command code movwf Command call I2C_WrCmd return ;----------------------- ;Set_Display_Off ; movlw 0xAE ; Command code ; movwf Command ; call I2C_WrCmd ; return ;----------------------- Set_Display_Clock ; Set Display Clock Divide Ratio / Oscillator Frequency movlw 0xD5 ; Command code1 movwf Command call I2C_WrCmd movlw 0x80 ; Command code2 movwf Command call I2C_WrCmd return ;----------------------- Set_Multiplex_Ratio ; movlw 0xA8 ; Command code1 movwf Command call I2C_WrCmd movlw 0x3F ; Command code2 movwf Command call I2C_WrCmd 14 return ;----------------------- Set_Display_Offset ; movlw 0xD3 ; Command code1 movwf Command call I2C_WrCmd movlw 0x00 ; Command code2 movwf Command call I2C_WrCmd return ;----------------------- Set_StartLine ;(0x00) movlw 0x40 ; Command code1 movwf Command call I2C_WrCmd return ;----------------------- Set_Charge_Pump ;(0x04) movlw 0x8D ; Command code1 movwf Command call I2C_WrCmd movlw 0x14 ; Command code2.0x14 (0x04) => Enable Charge Pump. 0x10 (0x00) => Disable Charge Pump movwf Command call I2C_WrCmd return ;----------------------- Set_Addressing_Mode ;(0x02) movlw 0x20 ; Command code1. Select Memory Addressing Mode movwf Command call I2C_WrCmd movlw 0x02 ; Command code2, 0x02 => Page Addressing Mode movwf Command call I2C_WrCmd return ;----------------------- Set_Segment_Remap ;(0x01) movlw 0xA1 ; Command code1. 0xA1 (0x01) => Column Address 0 Mapped to SEG127 movwf Command call I2C_WrCmd return ;----------------------- Set_Common_Remap ;(0x08) movlw 0xC8 ; Command code1. 0xC8 (0x08) => Scan from COM63 to 0 movwf Command call I2C_WrCmd return ;----------------------- Set_Common_Config ;(0x10) movlw 0xDA ; Command code1. Set COM Pins Hardware Configuration movwf Command call I2C_WrCmd movlw 0x10 ; Command code2, Alternative COM Pin Configuration/Disable COM Left/Right Re-Map movwf Command call I2C_WrCmd return ;----------------------- Set_Contrast_Control ;(0xCF) movlw 0x81 ; Command code1. Set Contrast Control movwf Command call I2C_WrCmd movlw 0xCF ; Command code2, Default => 0x7F movwf Command call I2C_WrCmd return ;----------------------- Set_Precharge_Period ;(0xF1) movlw 0xD9 ; Command code1. Set Pre-Charge Period movwf Command call I2C_WrCmd movlw 0xF1 ; Command code2, D[7:4] => Phase 2 Period in 1~15 Display Clocks.D[3:0] => Phase 1 Period in 1~15 Display Clocks movwf Command call I2C_WrCmd return ;----------------------- Set_VCOMH ;(0x40) movlw 0xDB ; Command code1. Set VCOMH Deselect Level movwf Command call I2C_WrCmd 15 movlw 0x40 ; Command code2, Default => 0x20 (0.77*VCC) movwf Command call I2C_WrCmd return ;----------------------- Set_Entire_Display_ON movlw 0xA4 ; Command code. 0xA4 (0x00) => Normal Display. 0xA5 (0x01) => Entire Display On movwf Command call I2C_WrCmd return ;----------------------- Set_Inverse_Display movlw 0xA6 ; Command code. 0xA6 (0x00) => Normal Display movwf Command call I2C_WrCmd return ;----------------------- LED_Fill movlw d'8' movwf y addlw 0xB0-1 movwf Command ; Command code 1 call I2C_WrCmd movlw 0x00 ; Command code 2. movwf Command call I2C_WrCmd movlw 0x10 ; Command code 3. movwf Command call I2C_WrCmd movlw d'128' ; change from d'128' movwf x movlw b'00000000' ; 0x00 = clear LED dots movwf Dat call I2C_WrData decfsz x,f goto $-4 decfsz y,d goto LED_Fill+1 return ;----------------------- LED_Set_Pos ; set LED POSITION at x,y movlw 0xB0 addwf y,d movwf Command ; Command code 1 call I2C_WrCmd movlw 0xf0 andwf x,d movwf temp RRF temp,f ; shift right 4 bits position RRf temp,f RRF temp,f RRF temp,d iorlw 0x10 movwf Command ; Command code 1 call I2C_WrCmd movlw 0x0f andwf x,d movwf Command ; Command code 1 call I2C_WrCmd return ;----------------------- Table_Offset ; get the table address for the single digit value (0 to 9) stored in W ; addlw -14 ; btfsc STATUS,C ; goto MAIN ; error encountered, reset clrf Offset1_high ; reset high order byte 16 clrf Offset2_high addlw 0 ; add zero to test if it is zero btfsc STATUS,Z goto Table_Offset1 movwf temp1 ; contains 0 to 14 in binary movlw d'0' ; clear W addlw d'32' ; add 32 in adavnce btfsc STATUS,C incf Offset1_high,f decfsz temp1,f ;skip if zero goto $-4 Table_Offset1 movwf Offset1_low movlw 16 addwf Offset1_low,d movwf Offset2_low ; second offset movfw Offset1_high btfsc STATUS,C addlw 1 movwf Offset2_high ; clrf Offset1_high ; reset high order byte ; clrf Offset2_high return ;------------------------------------- Offset1_address movfw Offset1_low movwf Offset_low movfw Offset1_high movwf Offset_high goto LED_Fill_1 Offset2_address movfw Offset2_low movwf Offset_low movfw Offset2_high movwf Offset_high goto LED_Fill_1 ;----------------------- LED_Fill_1 ; movlw d'8' ; movwf Offset_low ;offset movlw d'16' ; one display character has 16 display column movwf count1 LED_Fill_2 movfw Offset_low call Table movwf Dat call I2C_WrData incf Offset_low,f decfsz count1,f goto LED_Fill_2 return ;============================================================== ; OLED diaplay routine ; i/p : numeric value to display in W-reg ; x = display column number, value is in multiple of 8, eg 0,8,16,24,32.... ; y = display row number, value from 0 to 4 ;============================================================== OLED_Display_value call Table_Offset ; movlw 3 ; display line/row #3 ; movwf y ; movlw 8*0 ; display column #6 ; movwf x call LED_Set_Pos call Offset1_address 17 incf y,f ; movlw 4 ; movwf y ; movlw 8*0 ; movwf x call LED_Set_Pos call Offset2_address return ;******************************************************* ; Delay routines ;******************************************************* ;longdelay_routine ; clrf Delaycount0 ; reset Delaycount1 ; movlw .159 ; 2Hz (0.5S) ; movwf Delaycount0 ;delayloop2 ; call Delay_routine2 ; decfsz Delaycount0,f ; goto $-2 ; return ;--------------------- longdelay_routine2 clrf Delaycount2 ; reset Delaycount1 movlw D'100' movwf Delaycount2 delayloop4 call Delay_routine2 decfsz Delaycount2,f goto $-2 return ;--------------------- ;Delay_routine ; movlw .70 ; movwf Delaycount1 ; reset Delaycount1 ;Delay_routine1 ; decfsz Delaycount1,f ; goto $-1 ; return ;--------------------- Delay_routine2 clrf Delaycount1 ; reset Delaycount1 delayloop3 nop nop nop DECFSZ Delaycount1,f goto $-4 return ;====================================== ; 10us delay I2C_START_Bit and STOP bit ;====================================== Delay_10us movlw d'1' ; 1 x 3 = 3 + 1 + 1 + 2 +2 =9uS movwf Delaycount_s DECFSZ Delaycount_s,f goto $-1 return ;*********************************** ; OLED module Initialization Routine ;*********************************** OLED_Init movlw b'000010' movwf ACK ; CALL Set_Display_Off CALL Set_Display_Clock CALL Set_Multiplex_Ratio CALL Set_Display_Offset CALL Set_StartLine CALL Set_Charge_Pump CALL Set_Addressing_Mode CALL Set_Segment_Remap 18 CALL Set_Common_Remap CALL Set_Common_Config CALL Set_Contrast_Control CALL Set_Precharge_Period CALL Set_VCOMH call Set_Entire_Display_ON CALL Set_Inverse_Display ; normal display CALL Set_Display_On CALL LED_Fill return ;*********************************** ; MCU PIC12F1612 Initialisation ;*********************************** MCU_INIT BANKSEL OSCCON ; OSCILLATOR CONTROL REGISTER movlw b'01101010' ; ; |---------> 0= 4xPLL is disabled ; 1101-----> Internal Oscillator Frequency Select bits, 1101 = 4 MHz ; |----> Unimplemented: Read as ?0? ; 10--> System Clock Select bits, 1x = Internal oscillator block movwf OSCCON BANKSEL OSCTUNE ; OSCILLATOR TUNING REGISTER movlw b'00001000' ; ; ||--------> Unimplemented: Read as ?0? ; 000000--> Oscillator module is running at the factory-calibrated frequency movwf OSCTUNE BANKSEL TRISA movlw b'011111' ;configure RA0/SCL and RA1/SDA as input (high Z) and RA2 as analog i/p for ADC movwf TRISA ; RA4 as Rx (i/p)and RA5 as Tx (o/p) . RA3 as i/P, BANKSEL PORTA ; bank 0 movlw b'100000' ; clear RA0/SCL and RA1/SDA (Standby mode), RA5 (Tx) set to high (stdby) movwf PORTA BANKSEL LATA ; bank 0 movlw b'100000' ; clear RA0/SCL and RA1/SDA (Standby mode), RA5(Tx) as o/p, RA4(Rx) as i/p movwf LATA BANKSEL CM1CON0 movlw b'00000000' ; Turn comparator module OFF movwf CM1CON0 ; (for lowest power consumtion, and for dig.I/O) BANKSEL T1CON ; TIMER1 CONTROL REGISTER bcf T1CON,0 ; bit 0, TMR1ON = 0, disable timer1 T1CON BANKSEL OPTION_REG ; bank1 movlw b'10001111' ; CONFIGURE OPTION REG --> SET UP TIMER 0 ; 111----> SELECT PRESCALER RATE AS 1:256, 001 -> 1 : 4, 110 --> 1:64 for WDT, 111 --> 1:128 for WDT ; 1-------> PSA: Prescaler Assignment bit, 0 = Prescaler is assigned to the Timer0 module, 1 = Prescaler is NOT assigned to the Timer0 module, ; 0--------> TMR0SE: Timer0 Source Edge Select bit, 0 = Increment on low-to-high transition on T0CKI pin ; 0---------> TMR0CS: Timer0 Clock Source Select bit, 0 = Internal instruction cycle clock (FOSC/4) ; 0----------> INTEDG: Interrupt Edge Select bit, not relevant ; 1-----------> PORTA Pull-up Enable bit, 1 = pull-ups are disabled movwf OPTION_REG BANKSEL WPUA movlw b'00000000' ; CONFIGURE WEAK PULL-UP (WPUA) REG ; 0011----> WPUA<2:0>: Weak Pull-up Register bit,1 = Pull-up enabled, 0 = Pull-up disabled. ; 00--------> WPUA<5:4>: Weak Pull-up Register bit,1 = Pull-up enabled, 0 = Pull-up disabled movwf WPUA BANKSEL INTCON ; bank0 movlw b'00000000' ; setting INTCON: INTERRUPT CONTROL REGISTER ; 0-----------> disable GLOBAL INTERRUPT ENABLE BIT ; 0----------> disabled PEIE: Peripheral Interrupt Enable bit ; 0---------> enable TMR0IE: Timer0 Overflow Interrupt Enable bit ; 0--------> disable INTE: INT External Interrupt Enable bit ; 0-------> disable RABIE: PORTA Change Interrupt Enable bit(1) ; 0------> TMR0IF: Timer0 Overflow Interrupt Flag bit ; 0-----> INTF: INT External Interrupt Flag bit 19 ; 0----> RABIF: PORTA Change Interrupt Flag bit movwf INTCON BANKSEL ANSELA ; select ANSELA register (bank 1) movlw b'00000000' ; |||--------> not implemented ; 00000---> ANS4:ANS0: Analog Select bits, 00000 = RA0,RA1,RA2,RA4 and RA5 as digital i/p, movwf ANSELA BANKSEL ADCON0 ; ADC CONTROL REGISTER 0 movlw b'00001000' ; ; |----> ADON: ADC Enable bit, 0 = turn off ADC function, 1 = turn on ADC function ; |-----> GO/DONE: A/D Conversion Status bit, write 1 to start new ADC cycle, 0 = completion ADC cycle, or no activity in ADC ; xxxxx------> CHS<4:0>: Analog Channel Select bits, 00000 = AN0, 00010 = AN2 ; |-----------> Unimplemented: Read as ?0? movwf ADCON0 BANKSEL ADCON1 ; ADC CONTROL REGISTER 1 movlw b'11000000' ; ; ||----> ADPREF<1:0>: ADC Positive Voltage Reference Configuration bits. 00 = VRPOS is connected to VDD ; ||------> Unimplemented: Read as ?0? ; xxx--------> ADCS<2:0>: ADC Conversion Clock Select bits. 100 = FOSC/4, 1us ; |-----------> ADFM: ADC Result Format Select bit. 1 = Right justified movwf ADCON1 BANKSEL ADCON2 ; ADC CONTROL REGISTER 2 movlw b'00000000' ; ; ||||--------> TRIGSEL<3:0>: Auto-Conversion Trigger Selection bits. 0000 = No auto-conversion trigger selected ; ||||----> Unimplemented: Read as ?0? movwf ADCON2 BANKSEL FVRCON ; FIXED VOLTAGE REFERENCE CONTROL REGISTER movlw b'00000000' ; ; |-----------> FVREN: Fixed Voltage Reference Enable bit. 0 = disable, 1 = enable movwf FVRCON BANK0 ; bank0 clrf SECONDS_byte; reset RTC variables clrf MIN_byte clrf HR_byte clrf DAY_byte clrf DD_byte clrf MM_byte clrf YY_byte clrf sign ; reset digital temperature sensor variables clrf hundreds clrf tens clrf ones clrf onetenths return ;******************************************************************************* ; RTC/DS1307 interface routines ;******************************************************************************* RTC_INIT movlw 0x07 ; RTC_Control_Reg, 1Hz o/p at SQW movwf RTC_reg_value movlw 0x10 movwf RTC_reg_add call RTC_write_reg return ;===================================================== RTC_timedate_setting call I2C_START_Bit ; movlw RTC_Address_Wr ; Connect to DS1307 by sending its ID/Address on I2c Bus call I2C_WrByte call I2C_RdACK movlw 0x00 ; Request year RAM address call I2C_WrByte 20 call I2C_RdACK movlw 0x09 ; seconds Call I2C_WrByte ; receive the SECONDS byte call I2C_RdACK movlw 0x25 ; minites Call I2C_WrByte ; receive the SECONDS byte call I2C_RdACK movlw 0x15 ; hours Call I2C_WrByte ; receive the SECONDS byte call I2C_RdACK movlw 0x07 ; day Call I2C_WrByte ; receive the SECONDS byte call I2C_RdACK movlw 0x18 ; date Call I2C_WrByte ; receive the SECONDS byte call I2C_RdACK movlw 0x03 ; month Call I2C_WrByte ; receive the SECONDS byte call I2C_RdACK movlw 0x18 ; year Call I2C_WrByte ; receive the SECONDS byte call I2C_RdACK Call I2C_STOP_Bit return ;===================================================== ; RTC_write_reg ; i/p ; RTC_reg_add = RTC register address, 0 = seconds reg, 1 = minutes reg, 3 = hours reg, and so on ; RTC_reg_value = the value to write into the register selected ;===================================================== RTC_write_reg call I2C_START_Bit ; movlw RTC_Address_Wr ; Connect to DS1307 by sending its ID/Address on I2c Bus call I2C_WrByte call I2C_RdACK movlw RTC_reg_add ; Request year RAM address at 06H call I2C_WrByte call I2C_RdACK movfw RTC_reg_value ; year = 2018 Call I2C_WrByte ; receive the SECONDS byte call I2C_RdACK Call I2C_STOP_Bit return ;===================================================== ; RTC_read_reg, master read RTC register content ; i/p ; RTC_reg_add = RTC register address, 0 = seconds reg, 1 = minutes reg, 3 = hours reg, and so on ; RTC_reg_value = the register value to be read by the master ;===================================================== RTC_read_reg call I2C_START_Bit ; movlw RTC_Address_Wr ; Connect to DS1307 by sending its ID/Address on I2c Bus call I2C_WrByte 21 call I2C_RdACK movfw RTC_reg_add ; Request Sec RAM address call I2C_WrByte call I2C_RdACK Call I2C_STOP_Bit NOP call I2C_START_Bit ; movlw RTC_Address_Rd ; Connect to DS1307 by sending its ID/Address on I2c Bus call I2C_WrByte call I2C_RdACK ; Call I2C_RdByte ; receive the register value ; Call I2C_WrACK ; send No-acknoledge bit movfw charRx movwf RTC_reg_value Call I2C_STOP_Bit return ;===================================================== RTC_read_timedate ; read real time from DS1307 call I2C_START_Bit ; movlw RTC_Address_Wr ; Connect to DS1307 by sending its ID/Address on I2c Bus call I2C_WrByte call I2C_RdACK movfw 0x00 ; pointer to seconds reg address call I2C_WrByte call I2C_RdACK Call I2C_STOP_Bit NOP call I2C_START_Bit ; movlw RTC_Address_Rd ; Connect to DS1307 by sending its ID/Address on I2c Bus call I2C_WrByte call I2C_RdACK ; Call I2C_RdByte ; receive the register value Call I2C_WrACK ; send acknoledge bit movfw charRx movwf SECONDS_byte Call I2C_RdByte ; receive the register value Call I2C_WrACK ; send acknoledge bit movfw charRx movwf MIN_byte Call I2C_RdByte ; receive the register value Call I2C_WrACK ; send acknoledge bit movfw charRx movwf HR_byte Call I2C_RdByte ; receive the register value Call I2C_WrACK ; send acknoledge bit movfw charRx movwf DAY_byte Call I2C_RdByte ; receive the register value Call I2C_WrACK ; send acknoledge bit movfw charRx movwf DD_byte Call I2C_RdByte ; receive the register value Call I2C_WrACK ; send acknoledge bit movfw charRx movwf MM_byte Call I2C_RdByte ; receive the register value 22 ; Call I2C_WrACK ; send NO-acknoledge bit movfw charRx movwf YY_byte Call I2C_STOP_Bit return ;***************************************************************************** ; DS18B20 Digital Temperature Sensor Interface Routines ; to obtain temperature data from DS18B20 ;***************************************************************************** Gettemperature Call Ow.Reset ; MCU communicates the DS18B20 movlw 0xCC ; send 'skip rom' command call Ow.WrByte ; movlw 0x44 ; send 'convert' command call Ow.WrByte ; RdSlot Call Ow.RdBit ; conversion complete? BTFSS STATUS,C ; no, branch (wait), else goto RdSlot RdTemp Call Ow.Reset ; movlw 0xCC ; send 'skip rom' command call Ow.WrByte ; movlw 0xBE ; end 'read scratchpad' command call Ow.WrByte ; call Ow.RdByte ; MOVFW OwByte movwf TempLo ; save temperature lo call Ow.RdByte ; MOVFW OwByte movwf TempHi ; save temperature hi ; ; handle a negative temperature ; AbsFunc ; movlw 0x07 ; testing display 125.0 degree C ; movwf TempHi ; movlw 0xD0 ; movwf TempLo ; movfw TempHi ; movwf charTx ; Call serial_out ; ; movfw TempLo ; movwf charTx ; Call serial_out ; movlw 0x05 ; testing display 85.0 degree C ; movwf TempHi ; movlw 0x50 ; movwf TempLo ; movlw 0x01 ; testing display 25.1 degree C ; movwf TempHi ; movlw 0x91 ; movwf TempLo ; movlw 0x00 ; testing display 0.5 degree C ; movwf TempHi ; ; movlw 0x08 ; movwf TempLo ; movlw 0x00 ; testing display 0.0 degree C ; movwf TempHi ; ; movlw 0x00 ; movwf TempLo 23 ; movlw 0xFF ; testing display -0.5 degree C ; movwf TempHi ; FFF8h ; movlw 0xF8 ; movwf TempLo ; movlw 0xFF ; testing display -10.1 degree C ; movwf TempHi ; FF5Eh ; movlw 0x5E ; movwf TempLo ; movlw 0xFC ; testing display -55 degree C ; movwf TempHi ; FC90h ; movlw 0x90 ; movwf TempLo bcf negflag ; clear \"negative\" flag btfss TempHi,7 ; negative temperature? goto BinPrep ; no, branch, else comf TempLo,f ; two's compliment it comf TempHi,f ; incf TempLo,f ; BTFSC STATUS,Z ; incf TempHi,f ; bsf negflag ; indicate \"negative\" ; ; put the 7-bit Integer temperature (0..125) in TempHi and ; leave the 4-bit fraction in TempLo ; BinPrep movlw 0xF0 ; W = 11110000 andwf TempLo,d ; F = LLLLFFFF ---> W = LLLL0000, iorwf TempHi,f ; F = LLLL0HHH swapf TempHi,f ; F = 0HHHLLLL, value = 0 to 125 in decimal ; ; convert to decimal in \"hundreds\ ; Bin2BCD clrf hundreds ; clear hundreds digit movlw -10 ; wreg = -10 resetx movwf tens ; reset 'tens' to -10 div10x addwf TempHi,f ; subtract 10, borrow? BTFSS STATUS,C ; no, skip, else goto binxit ; branch (we're done) incfsz tens,f ; increment 'tens', overflow? goto div10x ; no, branch, else incf hundreds,f ; increment 'hundreds' goto resetx ; reset 'tens' binxit subwf tens,f ; fix -10 offset subwf TempHi,d ; fix -10 offset movwf ones ; ; ; \"onetenths\" = fraction * 10 / 16 ; movlw 0x0F ; andwf TempLo,f ; movf TempLo,d ; addwf TempLo,f ; *2, C=0 rlf TempLo,f ; *4, C=0 addwf TempLo,f ; *5, C=0 rlf TempLo,f ; *10 movlw 8 ; addwf TempLo,f ; rounding swapf TempLo,d ; pseudo divide by 16 andlw 0x0F ; movwf onetenths ; ; ; minus sign & leading zero suppression movlw 12 ; set the ' ' (space) character to sign in advance btfsc negflag ; positive then skip, else movlw 11 ; the '-' character movwf sign movfw hundreds ; hundreds == \"1\" or \"2\"? btfss STATUS,Z 24 goto return1 ; yes, branch, else movlw 12 ; the ' ' (space) character btfsc negflag ; positive then skip, else movlw 11 ; the '-' character movwf hundreds ; movlw 12 ; the ' ' (space) character movwf sign movfw tens ; tens != \"0\" skpnz ; yes, skip, else movlw 12 ; the ' ' (space) character movwf tens ; return1 return ;========================================================= ; DS18B20 \"One Wire\" communication subroutines. Using RA2 ;========================================================= Ow.Reset BANK1 bcf TRISA,2 ; set RA2/OwPin as o/p, RA2 low BANK0 movlw b'111000' ; RA0 and RA1 and RA2 always at low, RA5/Tx always at high movwf PORTA ; ; clrf PORTA movlw 552/4 ; call Delay ; delay 552 usecs & release bus movlw 552/4 ; goto Delay ; delay 552 usecs & RETLW 0 Ow.WrByte movwf OwByte ; store byte movlw 8 ; movwf count ; wrloop rrf OwByte,f ; move bit to carry call Ow.WrBit ; send it decfsz count,f ; done? goto wrloop ; no, branch, else RETURN ; Ow.WrBit BANK1 bcf TRISA,2 ; set RA2/OwPin as o/p and RA2 at logic low voltage BTFSC STATUS,C ; send '0' at RA2? yes, skip, else bsf TRISA,2 ; send '1' at RA2, by external pull resistor movlw 56/4 ; finish 60 usec slot Delay movwf temp ; decfsz temp,d ; goto Delay ; BANK1 bsf TRISA,2 ; send '1' at RA2, by external pull resistor BANK0 RETURN ; Ow.RdByte movlw 8 ; movwf count ; rdloop call Ow.RdBit ; return, C = bit received rrf OwByte,f ; move Carry into byte decfsz count,f ; built a full byte? goto rdloop ; no, branch, else BANK0 RETURN ; Ow.RdBit BANK1 bcf TRISA,2 ; set RA2 as o/p mode, logic low , for 3us nop 25 bsf TRISA,2 ; set RA2 as input mode (Hi-Impediance) so as to release the line ; movlw 3 ; wait 10 usecs for DS18B20 to respond movwf temp ; decfsz temp,f ; goto $-1 ; sample between 13-14 usecs BANK0 bcf STATUS,C ; first assume read bit = 0 btfsc PORTA,2 ; Check RA2, a '0'? yes, skip (C=0), else bsf STATUS,C ; indicate a '1' (C=1) goto Delay-1 ; delay 60 usecs & return ;******************************************************************************* ; Serial Port Routine (0x35 byte long) ; configure RA5 (Tx) and RA4 (Rx) as serial port to ; communicate with PC serial dumb terminal (or via blue tooth ; module HC-06). Serial comm is set at 9600,N,8,1... ; ;******************************************************************************* Serial_port_check call serial_in ; high for 0.125S, low for 0.125S, total 0.247S, or 4.05Hz call Delay_s ; bit duration = 0.104uS or 13 instruction cycles ;----------------------------------------------------------------------------- output_serial movfw charRx ; get the last serial_ind byte ADDLW 1 movwf charTx ; serial out the serial_ind byte call serial_out BANKSEL PORTA return ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- serial_in ; Baud rate 9600,N,8,1 banksel PORTA BTFSC PORTA,4 ; Bit Test f, Skip if Set (no start bit received) goto $-1 ; if GP4 low, start bit received, goto serial_in1 ; loop back to contunue awaiting start bit serial_in1 call Delay_s2 ; half bit delay movlw d'8' ; 8-bit to be serial in at GP4 (Rx,pin3) movwf count ; serial_in2 RRF charRx,f ; Rotate Right f through Carry call Delay_s ; full bit duration dalay bsf charRx,7 ; assume new bit to be received is logic high BTFSS PORTA,4 ; Bit Test f, Skip if Set (new bit received is logic high) bcf charRx,7 ; new bit received is logic low, so clear bit7 DECFSZ count,f ; Decrement f, Skip (have received 8 bit) if 0 goto serial_in2 ; to receive next high order bit return ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- serial_out ; Baud rate 9600,N,8,1 banksel LATA bcf LATA,5 ; start bit (logic low) serial out at GP5 (Tx,pin2) call Delay_s ; bit duration = 0.104uS or 13 instruction cycles movlw d'8' ; 8-bit to be serial out at RA5 (Tx,pin2) movwf count ; serial_out1 RRF charTx,f ; Rotate Right f through Carry BTFSS STATUS,C ; Bit Test f, Skip if Set goto serial_out2 bsf LATA,5 ; data bit '1 (high) serial out at GP5 (pin2) call Delay_s ; bit duration = 0.104uS or 13 instruction cycles 26 goto serial_out3 serial_out2 bcf LATA,5 ; data bit '0' (low) serial out at GP5 (pin2) call Delay_s ; bit duration = 0.104uS or 13 instruction cycles serial_out3 DECFSZ count,f ; Decrement f, Skip (have sent out all 8 bit) if 0 goto serial_out1 ; loop back to serial out next data bit bsf LATA,5 ; top bit (high) serial out at GP5 (pin2) call Delay_s ; bit duration = 0.104mS or 104uS for baud rate 9600 call Delay_s2 ; pause between 2 characters BANK0 return ;----------------------------------------------------------------------------------------------- ; Delay Routine for serial comm. Baud rate 9600 (OSC Freq = 4MHz, instruction cycle = 1uS) ;----------------------------------------------------------------------------------------------- Delay_s movlw d'32' ; 34 x 3 =102 + 1 + 1 + 2 + 2 = 104, or 102uS movwf Delaycount_s delay_s1 DECFSZ Delaycount_s,f goto delay_s1 nop return Delay_s2 ; half bit duration delay movlw d'15' ; 16 x 3 = 48 + 1 + 1 + 2 +2 = 54, or 52uS movwf Delaycount_s delay_s3 DECFSZ Delaycount_s,f goto delay_s3 return ;********************************************************************** ; Binary (12-bit) to BCD conversion routine ; i/p -- NUMH1(4-bit) + NUMLO(8-bit) ; o/p -- D3 (thousands), D2, D1, D0 (ones) ;********************************************************************** Bin_to_BCD ; 12 bit binary to BCD conversion movf NUMHI,w iorlw 0xF0 ;w=H2-16 movwf D1 ;D1=H2-16 addwf D1,f ;D1=H2*2-32 addwf D1,f ;D1=H2*3-48 movwf D2 ;D2=H2-16 addlw -D'5' ;w=H2-21 addwf D2,f ;D2=H2*2-37 Done! addlw D'41' ;w=H2+20 movwf D0 ;D0=H2+20 swapf NUMLO,w iorlw 0xF0 ;w=H1-16 addwf D1,f ;D1=H2*3+H1-64 addwf D0,f ;D0=H2+H1+4, C=1 rlf D0,f ;D0=(H2+H1)*2+9, C=0 comf D0,f ;D0=-(H2+H1)*2-10 rlf D0,f ;D0=-(H2+H1)*4-20 movf NUMLO,w andlw 0x0F ;w=H0 addwf D0,f ;D0=H0-(H2+H1)*4-20 Done! rlf D1,f ;C=0, D1=H2*6+H1*2-128 Done! movlw D'5' movwf D3 movlw D'10' mod0 addwf D0,f ;D(X)=D(X)mod10 decf D1,f ;D(X+1)=D(X+1)+D(X)div10 skpc goto mod0 27 mod1 addwf D1,f decf D2,f skpc goto mod1 mod2 addwf D2,f decf D3,f skpc goto mod2 return END 28

因篇幅问题不能全部显示,请点此查看更多更全内容