ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Четверг
21 ноября
98843 Топик полностью
AVR (07.09.2007 13:55, просмотров: 361) ответил Vladimir Ljaschko на Дай списать проект за шоколадку? :)
С 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>