С CAN никогда не работал, и не планирую - нету в моей тематике такого интерфейса как класса. Тестовый рабочий АСМ-проектик для поиграццо - внутри <asm>
;------------------------------------------------------------------------------
.psize 0
;------------------------------------------------------------------------------
; Processor Setup
;------------------------------------------------------------------------------
;__30F6012A = 1
.include "p30f6012a.inc"
.list
;------------------------------------------------------------------------------
; Configuration Fuses
;------------------------------------------------------------------------------
config __FOSC, CSW_FSCM_OFF & FRC_PLL16 ;MCU troughput = 29.5 MIPS
config __FWDT, WDT_OFF
config __FBORPOR, PBOR_ON & BORV_27 & PWRT_16 & MCLR_EN
config __FGS, CODE_PROT_OFF
;------------------------------------------------------------------------------
; Global Equates & Symbols
;------------------------------------------------------------------------------
baud = 115200 ; UART1 Baud rate, Baud
fcy = 7372800*16/4 ; MCU machine cycle frequency, Hz
baudrate = (((fcy/baud)/16)-1) ; Calculated BRG value
I2Cfreq = 400 ; I2C bus clock freqency, KHz !!! ERROR in formula above 400 KHz
I2Cbr = (fcy/(I2Cfreq*1000)-fcy/1111111)-1 ; Calculate I2CBRG reload value, !!! 600 KHz gives 1 MHz
LCD_addr = 0x78 ; PCF8535 based LCD I2C slave address
CON1 = 0b10000000 ; LCD control command #1
CON2 = 0b01000000 ; LCD control command #2
LED1 = RD4 ; LED1 connected to RD4 (1 = ON)
LED2 = RD5 ; LED2 connected to RD5 (1 = ON)
LED3 = RD6 ; LED1 connected to RD6 (1 = ON)
LED4 = RD7 ; LED2 connected to RD7 (1 = ON)
LCD_res = RF6 ; LCD /RESET connected to RF6
SCL = RG2 ; I2C SCL
SDA = RG3 ; I2C SDA
S1 = RC13 ; SW1 connected to RC13 (0 = ON)
S2 = RC14 ; SW2 connected to RC14 (0 = ON)
extitoa = 0 ; itoa extended range (65536..99999) flag
;------------------------------------------------------------------------------
; Global Declarations
;------------------------------------------------------------------------------
.global __reset ; Declare main code start name global
.global __U1TXInterrupt ; Declare USART1 TX ISR name global
;.global __U1RXInterrupt ; Declare USART1 TX ISR name global
;------------------------------------------------------------------------------
; Global Initialised Variables
;------------------------------------------------------------------------------
.section .xbss ; X data memory space
ascptr: .space 2
flags1: .space 2
u1txptr: .space 2 ;UART1 Tx pointer
;------------------------------------------------------------------------------
.section .ybss ; Y data memory space
ascbuf: .space 16
;------------------------------------------------------------------------------
;Sec 1.0.Main Code
;------------------------------------------------------------------------------
.section .text
__reset: ; The label for the first line of code
mov #__SP_init,w15 ; Initalize the Stack Pointer
mov #__SPLIM_init,w0 ; Initialize the Stack Pointer Limit Register
mov w0,SPLIM
nop ; Add NOP to follow SPLIM initialization
clr PSVPAG ; Assume 32K limit for code space data access
mov #(1 << PSV)|(1 << IF)|(1 << US)|(1 << ACCSAT),w0 ; Enable Program Space Visibility,
mov w0,CORCON ; select MAC unsigned integer super saturation mode
rcall init_ports
rcall init_UART1 ; Setup the UART1 for usage
; bra test_mul16x32
; bra test_mul32
; bra test_atoi
; bra test_atol
; bra test_div3
; bra test_div10
; bra test_sqrt16
; bra test_mirror
; bra test_mirror2
; bra test_RS232
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; I/O ports setup
init_ports:
mov #0xFF0F,w0 ; Set RD7 to RD4 as outputs
mov w0,TRISD
bclr TRISF,#LCD_res ; Set LCD_res as output
clr LATD
return
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; UART1 setup
init_UART1:
mov #baudrate,w0 ; Set UART1 Baudrate
mov w0,U1BRG ;
clr U1MODE ; Enable UART1 for 8-bit data,
bset U1MODE,#UARTEN ; no parity, 1 STOP bit,
; no flow control, no wakeup
mov #(4 << U1TXIP0)|(4 << U1RXIP0),w0 ; Set UART1 TX & RX IPLs to 4
mov w0,IPC2 ;
clr U1STA ; Clear status flags
bset U1STA,#UTXEN ; Enable transmit, set tx int flag
return
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; Initiates sending of an ASCIIZ message [w0] via UART1 using U1TX interrupt
sendmsg:
mov w4,u1txptr ; Load UART1 TX pointer
bset IEC0,#U1TXIE ; Enable UART1 transmit interrupt
u1wait:
btsc IEC0,#U1TXIE ; Wait until it is disabled by ISR
bra u1wait ;
return
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; Converts a 5-byte ASCII numerical string [w4] to an integer w0
; Treats all 5 ASCII characters as valid numbers '0..9' - no (isnumber) check
; Trashes w1, w2, w5, w6, w8, ACCA
; 34 clocks including RETURN, 17 program words, 5 constant words (part of atol reused)
atoi:
push CORCON ; Save Core Control register
bset CORCON,#US ; Force unsigned MAC mode
push w4 ; Save ASCII pointer
mov #psvoffset(atoltab),w8 ; Initialize coeff pointer to a RAM mapped table in code space
mov #15,w2 ; w2 = 0x0F = bit mask for a single char atoi
clr A,[w8] =2,w6 ; Clear ACCA, pre-fetch a first coeff
bra atoi_e ; Enter a lower part of atol
;------------------------------------------------------------------------------
; Converts a 10-byte ASCII numerical string [w4] to a long integer w1w0
; Treats all 10 ASCII characters as valid numbers '0..9' - no (isnumber) check
; Trashes w2, w5, w6, w8, ACCA
; 54 clocks including RETURN, 25 program words, 5 constant words
atol:
push CORCON ; Save Core Control register
bset CORCON,#US ; Force unsigned MAC mode
push w4 ; Save ASCII pointer
mov #psvoffset(atoltab),w8 ; Initialize coeff pointer to a RAM mapped table in code space
mov #15,w2 ; w2 = 0x0F = bit mask for a single char atoi
clr w5 ; w5h must remain zeroed all the time
clr A,[w8] =2,w6 ; Clear ACCA, pre-fetch a first coeff
do #4,1f ; Repeat the following 5 times to calculate MSW/100,000:
and.b w2,[w4 ],w5 ; - read next ASCII char and convert it to a binary word 0..9 in w5
1: mac w5*w6,A,[w8] =2,w6 ; - MAC, advance table ptr and pre-fetch next coeff
mov #psvoffset(atoltab),w8 ; Reinitialize coeff pointer to a RAM mapped table in code space
mov ACCAL,w5 ; MSW/100,000 calculated, now multiply it by 100,000
mpy w5*w6,A,[w8] =2,w6 ; ACCA = ACCA*50,000, pre-fetch a first coeff
sftac A,#-1 ; ACCA = ACCA*2*50,000 = ACCA*100,000
atoi_e: ; External entry point for atoi
clr w5 ; w5h must remain zeroed all the time
do #4,1f ; Repeat the following 5 times to calculate LSW (MSW*100,100):
and.b w2,[w4 ],w5 ; - read next ASCII char and convert it to a binary word 0..9 in w5
1: mac w5*w6,A,[w8] =2,w6 ; - MAC, advance table ptr and pre-fetch next coeff
mov ACCAL,w0 ; Read result to w1w0
mov ACCAH,w1 ;
pop w4 ; Restore ASCII pointer
pop CORCON ; Restore Core Control register
return
atoltab:
.word 10000,1000,100,10,1,50000
;------------------------------------------------------------------------------
;------------------------------------------------------------------
; Converts a binary byte w0L (0..255) to a packed BCD value in w0
; w0.11..8 = hundreds, w0.7..4 = tens, w0.3..0 = units
; Registers trashed: NONE
; 19 clocks including RETURN, 15 program words
byte2bcd:
push.d w2 ; Save w2w3
push w1 ; Save w1
ze w0,w0 ; Convert byte w0 to a word w0
mov #656,w1 ; Load a "magic number"
mul.uu w0,w1,w0 ; w1L = BCD hundreds, w0 = "remainder"
swap w1 ; w1H = BCD hundreds
mul.uu w0,#10,w2 ; w3 = BCD tens, w2 = "remainder"
swap.b w3 ; w3.4..7 = BCD tens
ior w3,w1,w1 ; w1.11..8 = BCD hundreds, w1.7..4 = BCD tens
mul.uu w2,#10,w2 ; w3 = BCD units
ior.b w1,w3,w1 ; w1H = BCD hundreds, w1L = BCD tens, BCD units
mov w1,w0 ; w0H = BCD hundreds, w0L = BCD tens, BCD units
pop w1 ; Restore w1
pop.d w2 ; Restore w3w2
return
;------------------------------------------------------------------
;------------------------------------------------------------------
; Divides a 16-bit number N in W0 by 3 (result in W1) using a multiplication by a scaled
; reciprocal of 3 ("magic number"). Doesn't calculate a remainder
; Registers trashed: W0
; 5 clocks including RETURN (2 clocks if inline), 3(2) program words
div3:
mov #0x5556,w1 ; w0 = X
mul.uu w0,w1,w0 ; w1 = X/3
return
;------------------------------------------------------------------
;------------------------------------------------------------------------------
; Divides a 16-bit number N in W0 (result in W1) by 10 using a multiplication by a scaled
; reciprocal of 10 ("magic number"). Doesn't calculate a remainder
; Registers trashed: W0
; 6 clocks including RETURN (3 clocks inline), 4(3) program words
div10:
mov #65536*8/10 1,w1 ; 52429 = 0xCCCD
mul.uu w0,w1,w0 ; w1=MSW(w0*65536*8/10)
lsr w1,#3,w1 ; w1=w1/8=N/10
return
;------------------------------------------------------------------------------
;------------------------------------------------------------------
; Mirrors a byte W0 to W1
; Registers trashed: NONE
; 16 clocks including RETURN, 14 program words
mirror:
mov.b w0,w1
and.b #0x55,w0
sl w0,w0
and.b #0xAA,w1
lsr w1,w1
ior.b w0,w1,w0
mov.b w0,w1
and.b #0x33,w0
sl w0,#2,w0
and.b #0xCC,w1
lsr w1,#2,w1
ior.b w0,w1,w0
swap.b w0
return
;------------------------------------------------------------------------------
;------------------------------------------------------------------
; Mirrors a byte w0 to w1 using rotates and a DO loop
; Registers trashed: NONE
; 17 clocks including RETURN, 9 program words
mirror2:
mov.b w0,w1
do #3,0f
rlc.b w0,w0
0: rrc.b w1,w1
rlc.b w0,w0
sl w0,#4,w0
and w1,w0,w1
return
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; Unsigned w0*w1w2 = w456, all Big Endian
; 9 clocks including return, 7 program words
; Registers trashed: NONE
mul16x32:
push w7
mul.uu w0,w1,w4
mul.uu w0,w2,w6
add w5,w6,w5
addc w7,#0,w6
pop w7
return
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; Unsigned w01*w23 = w4567, all Big Endian
; 18 clocks including return, 14 program words
; Registers trashed: NONE
mul32:
push.d w8
mul.uu w0,w2,w4
mul.uu w1,w2,w6
add w5,w6,w5
addc w7,#0,w6
mul.uu w0,w3,w8
add w5,w8,w5
addc w6,w9,w6
mul.uu w1,w3,w8
addc w9,#0,w9
add w6,w8,w6
addc w9,#0,w7
pop.d w8
return
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; 16-bit integer square root
;
; Algorithm:
; 1. Calculate a rough result estimation as 2^(Nbits(X)/2)
; 2. Multiply the found rough result by itself (square),
; 3. If a square is bigger than X then make the bit 0,
; 4. Otherwise, keep the one bit.
; 5. Keep shifting/squareing for all N (max 8) bits.
;
; w4 = X
; w6 = result
;
; w0:w1 scratch
; w2 = iteration counter/bit pointer
;
; 20..62 clocks, 18 program words
sqrt16:
clr w6 ; Zero a raw result
push.s ; Save w0..w3, SR
sqrt16e:
ff1l w4,w2 ; Find a leftmost "1" position in X (K)
bra c,3f ; Exit if X = 0
subr w2,#16,w2 ; Calculate a number of significant bits in X (N=16-K)
lsr w2,w2 ; and divide it by 2 to get a first rough result estimation
bclr SR,#Z ; Ensure Z =0 for BSW in a 1st iteration
do w2,1f ; Repeat Nbits/2 times
mov DCOUNT,w2 ; w2 = M = current rolling "1" bit number
bsw.z w6,w2 ; Set an Mth bit of a result
mul.uu w6,w6,w0 ; Square a raw result
cp w4,w0 ; Compare a squared raw result with X (CY is set if op1 >= op2!)
bra z,2f ; Break a DO loop if an exact square is calculated
1: bsw.c w6,w2 ; Reset an Mth bit of a result if squared > X
2: bset CORCON,#EDT ; Handle an early DO termination if exact sqrt
3: pop.s ; Restore w0..w3, SR
return
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; ISRs
;------------------------------------------------------------------------------
U1TXInterrupt:
bclr IFS0,#U1TXIF ; Clear UART1 transmit interrupt flag
push w0
mov u1txptr,w0 ; Read a next string byte to w0
mov.b [w0],w0 ;
inc u1txptr ; Advance a string pointer
cp0.b w0 ; Exit if the byte equals to zero
bra z,u1t_reti1 ; and disable further tx interrupts
mov w0,U1TXREG ; Send a byte via UART1 and exit normally
pop w0
retfie
u1t_reti1:
bclr IEC0,#U1TXIE ; Disable further UART1 transmit interrupts
bset IFS0,#U1TXIF ; Pre-set UART1 transmit interrupt flag
pop w0
retfie
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; A primitive timer interrupt driven caroussel task switcher example
; PR1 contains a current carrousel position
; !!! TRASHES w0 !!!
__T1Interrupt:
BCLR IFS0,#T1IF ; clear TMR1 int Flag
inc2 PR1 ; Update function address table index by adding 2 to it
MOV #tbloffset(TBLtoGOTO),w0 ; get the offset of my table of function calls into W0 reg
add PR1,WREG ; Add scaled index value to WREG (= W0)
tblrdl [w0],[w15 ] ; put lower address of table entry on stack first
tblrdh [w0],[w15 ] ; put upper address of table entry on stack last
return
TBLtoGOTO:
.pword FUNC1 ; Address of FUNC1
.pword FUNC2 ; Address of FUNC2
.pword FUNC3 ; Address of FUNC3
.pword FUNC4 ; Address of FUNC4
FUNC1:
; Place a FUNC1 code here
RETFIE
FUNC2:
; Place a FUNC2 code here
RETFIE
FUNC3:
; Place a FUNC3 code here
RETFIE
FUNC4:
; Place a FUNC4 code here
RETFIE
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; Constants in CODE memory, e.g. message texts
;------------------------------------------------------------------------------
hellomsg:
.asciiz "Hello, dsPIC!"
;------------------------------------------------------------------------------
.end
;------------------------------------------------------------------------------
</asm>
-
- Я в самом начале пути, результат ассемблирования пока такой, если есть комментарии, буду счастлив Vladimir Ljaschko(1844 знак., 13.09.2007 11:04)
- У меня все собирается с полпинка, только два ворнинга на атрибуты к xbss/ybss, как и положено. Ты пересобрал для dsPIC30F4012 - а директиву .include поменял? Дай-ка сюда ВЕСЬ свой код в тегах <asm> - AVR(13.09.2007 11:52)
- include поменял, управление выводом для ЖКИ убрал (в 4012 отсутствует). И все. Vladimir Ljaschko(16291 знак., 13.09.2007 14:03)
- До вечера теперь жди - отъехать надо - AVR(13.09.2007 12:45)
- У меня все собирается с полпинка, только два ворнинга на атрибуты к xbss/ybss, как и положено. Ты пересобрал для dsPIC30F4012 - а директиву .include поменял? Дай-ка сюда ВЕСЬ свой код в тегах <asm> - AVR(13.09.2007 11:52)
- Да, что за ЖКИ? - Vladimir Ljaschko(07.09.2007 14:11)
- Дополнительно - почитай этот пост --> - AVR(07.09.2007 13:57, ссылка)
- Спасибо, завалил :) - Vladimir Ljaschko(07.09.2007 14:07)
- Я в самом начале пути, результат ассемблирования пока такой, если есть комментарии, буду счастлив Vladimir Ljaschko(1844 знак., 13.09.2007 11:04)