Advertisement
Guest User

Untitled

a guest
Nov 23rd, 2014
167
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.70 KB | None | 0 0
  1. /*
  2. * eVm1a.asm
  3. * This program is a simple voltmeter application that will intake
  4. an analog signal, convert it to a digital signal, and then display the
  5. voltage onto an LCD display. Data will be transmitted serially
  6.  
  7. This will run continously
  8. * Created: 11/12/2014
  9. * Author: Christopher Earls And Kevin Kim
  10. Lab: 02- Bench 9
  11. LAB 10
  12. */
  13.  
  14. //Sets the ISR and the initial program
  15.  
  16. .org 0
  17. rjmp hard_reset
  18.  
  19. ;.org $014
  20. ;rjmp complete_isr
  21.  
  22.  
  23. .nolist
  24. .include "m16def.inc"
  25. .list
  26.  
  27. .include "lcd_dog_asm_driver_m16A.inc"
  28.  
  29. hard_reset: ;This subroutine ios a hard reset, it completely re-initializes all aspects of the circuit.
  30.  
  31. ;configure PA7 as an INPUT
  32. ldi r16, $00 ;Load all or porta with 0's
  33. out DDRA, r16 ;Porta as input
  34. ldi r16, $FF ;load r16 with all 1's
  35. out PORTD, r16 ;Enable pullup resistors
  36.  
  37. ;configure Port B as Output, PB0
  38. ldi r16, $BF ;load r16 with all ones
  39. out DDRB, r16 ;port b all outputs
  40. ldi r16, $40
  41. out PORTB, r16 ;enable pullup resistor
  42. SBI PORTB, 0 ;sET PORT bIT 0 to 1 as a disable so you can use the LCD dog
  43.  
  44.  
  45. ;initialize stack pointer register
  46. ldi r16, LOW(RAMEND) ; load SPL with low byte of
  47. out SPL, r16 ; RAMEND address.
  48. ldi r16, HIGH(RAMEND) ; load SPH with high byte of
  49. out SPH, r16 ; RAMEND address.
  50.  
  51. sei ; set the global interrupt
  52.  
  53.  
  54.  
  55. //Initial display for the bottom two lines, this will take care of the bottom two liens of text as they do not change in the program.
  56. //It is also good to check if the LCD is prperly on and displaying correctly.
  57.  
  58. init_display:
  59. rCALL init_lcd_dog //initializes LCD for display
  60.  
  61.  
  62. ;load 1st line of prompt message into dbuff2
  63. ldi ZH, high(line1_message<<1) ;
  64. ldi ZL, low(line1_message<<1) ;
  65. rcall load_msg ; load message into buffer(s).
  66.  
  67. ;load 2st line of prompt message into dbuff2
  68. ldi ZH, high(line2_message<<1) ;
  69. ldi ZL, low(line2_message<<1) ;
  70. rcall load_msg ; load message into buffer(s).
  71.  
  72. ;load 3nd line of prompt message into dbuff3
  73. ldi ZH, high(line3_message<<1) ;
  74. ldi ZL, low(line3_message<<1) ;
  75. rcall load_msg ; load message into buffer(s).
  76. rcall update_lcd_dog
  77.  
  78. //this is the main code, when the ADC is complete, it will call out to the Violtage reading function and then will
  79. //use the arithmatic to change it to a displayable value, This also includes the reset function.
  80.  
  81. reset:
  82. ;clt //clears the tflag initially
  83. ;call SPI_MasterInit //initializes the SPI master control
  84. ;call adc_init
  85. main:
  86. ;BRTS adc_read //if t flag is set, continue on
  87. call adc_read
  88.  
  89. rjmp main
  90.  
  91.  
  92.  
  93.  
  94.  
  95. ;This code will initialize the master/slave commands for the SPI interfacing.
  96. ;This is proveded by the Atmel data sheets
  97. init_adc:
  98. ldi r16, $50
  99. out SPCR, R16 ;Set up control register
  100. ldi r16, $00
  101. out SPSR, R16 ;Setup status register
  102. ret
  103.  
  104. adc_read:
  105. rcall init_adc ;initialize SPI for the ADC
  106. cbi PORTB, 0 ;Turn on the ADC
  107. rcall delay_9us ;wait 9us for the adc to turn on
  108. ldi r16, $00
  109. ;out SPSR, r16 ;Clear out the SPSR register
  110. out spdr, r16 ;clean out the data register to start a conversion
  111.  
  112. rcall wait
  113.  
  114. in r19, SPDR ;Intake the upper byte from the conversion
  115. andi r19, $0f ;mask any unnecessary data
  116. ldi r16, $00 ;load r16 with 0 to restart next 8 bits
  117. ;out SPSR, r16 ;Clear interrupt on the status register
  118. out SPDR, r16 ;Start serial transfer
  119.  
  120. rcall wait ;Will come into the wait for the finished transfer
  121.  
  122. in r18, SPDR ;Intake the lower 8 bit s for the conversion.
  123. mov r17, r19
  124. mov r16, r18
  125.  
  126. sbi PORTB, 0 ;Turn off the ADC before the LCD is used
  127. ;rcall init_spi_lcd ;Update the SPI so that it will display rather than use the ADC
  128.  
  129. rcall bin2BCD16
  130. rcall unpack2r4r0 ;unpack the values to bcd and ascii
  131.  
  132. STS dsp_buff_1, r5 ;Places the numbers onto the display
  133. STS dsp_buff_1+2, r6
  134. sts dsp_buff_1+3, r7
  135. sts dsp_buff_1+4, r8
  136. STS dsp_buff_1+5, r9
  137.  
  138. rcall update_lcd_dog ;updates the LCD
  139. jmp reset ;restarts the program
  140.  
  141.  
  142.  
  143.  
  144. ;This subroutine will check if the SPI transfer is completed, and will jump back once finished
  145. wait:
  146. in r16, SPSR ;check if the interrupt is triggered
  147. andi r16, $80 ;mask all but bit 7
  148. cpi r16, $80 ;Check if the data transfer is finished
  149. brne wait ;if not, it will loop
  150. ret ;if it is, it will return
  151.  
  152.  
  153.  
  154.  
  155. delay_9us:
  156. nop ; fine tune delay
  157. nop
  158. push r24
  159. ldi r24, 0x01 ; load delay count.
  160. d10_loop: dec r24 ; count down to
  161. brne d10_loop ; zero.
  162. pop r24
  163. ret
  164.  
  165.  
  166.  
  167. /* ;***************************************************************************
  168. ;*
  169. ;* "div32u" - 32/32 Bit Unsigned Division
  170. ;*
  171. ;* Ken Short
  172. ;*
  173. ;* This subroutine divides the two 32-bit numbers
  174. ;* "dd32u3:dd32u2:dd32u1:dd32u0" (dividend) and "dv32u3:dv32u2:dv32u3:dv32u2"
  175. ;* (divisor).
  176. ;* The result is placed in "dres32u3:dres32u2:dres32u3:dres32u2" and the
  177. ;* remainder in "drem32u3:drem32u2:drem32u3:drem32u2".
  178. ;*
  179. ;* Number of words :
  180. ;* Number of cycles :655/751 (Min/Max) ATmega16
  181. ;* #Low registers used :2 (drem16uL,drem16uH)
  182. ;* #High registers used :5 (dres16uL/dd16uL,dres16uH/dd16uH,dv16uL,dv16uH,
  183. ;* dcnt16u)
  184. ;* A $0000 divisor returns $FFFF
  185. ;*
  186. ;***************************************************************************
  187.  
  188. ;***** Subroutine Register Variables
  189.  
  190. .def drem32u0=r12 ;remainder
  191. .def drem32u1=r13
  192. .def drem32u2=r14
  193. .def drem32u3=r15
  194.  
  195. .def dres32u0=r18 ;result (quotient)
  196. .def dres32u1=r19
  197. .def dres32u2=r20
  198. .def dres32u3=r21
  199.  
  200. .def dd32u0 =r18 ;dividend
  201. .def dd32u1 =r19
  202. .def dd32u2 =r20
  203. .def dd32u3 =r21
  204.  
  205. .def dv32u0 =r22 ;divisor
  206. .def dv32u1 =r23
  207. .def dv32u2 =r24
  208. .def dv32u3 =r25
  209.  
  210. .def dcnt32u =r17
  211.  
  212. ;***** Code
  213.  
  214. div32u:
  215. clr drem32u0 ;clear remainder Low byte
  216. clr drem32u1
  217. clr drem32u2
  218. sub drem32u3,drem32u3;clear remainder High byte and carry
  219. ldi dcnt32u,33 ;init loop counter
  220. d32u_1:
  221. rol dd32u0 ;shift left dividend
  222. rol dd32u1
  223. rol dd32u2
  224. rol dd32u3
  225. dec dcnt32u ;decrement counter
  226. brne d32u_2 ;if done
  227. ret ; return
  228. d32u_2:
  229. rol drem32u0 ;shift dividend into remainder
  230. rol drem32u1
  231. rol drem32u2
  232. rol drem32u3
  233.  
  234. sub drem32u0,dv32u0 ;remainder = remainder - divisor
  235. sbc drem32u1,dv32u1
  236. sbc drem32u2,dv32u2
  237. sbc drem32u3,dv32u3 ;
  238. brcc d32u_3 ; branch if reult is pos or zero
  239.  
  240. add drem32u0,dv32u0 ; if result negative restore remainder
  241. adc drem32u1,dv32u1
  242. adc drem32u2,dv32u2
  243. adc drem32u3,dv32u3
  244. clc ; clear carry to be shifted into result
  245. rjmp d32u_1 ;else
  246. d32u_3: sec ; set carry to be shifted into result
  247. rjmp d32u_1
  248.  
  249.  
  250.  
  251. */
  252.  
  253.  
  254.  
  255.  
  256.  
  257. /* ;***************************************************************************
  258. ;*
  259. ;* "mpy16u" - 16x16 Bit Unsigned Multiplication
  260. ;*
  261. ;* This subroutine multiplies the two 16-bit register variables
  262. ;* mp16uH:mp16uL and mc16uH:mc16uL.
  263. ;* The result is placed in m16u3:m16u2:m16u1:m16u0.
  264. ;*
  265. ;* Number of words :14 + return
  266. ;* Number of cycles :153 + return
  267. ;* Low registers used :None
  268. ;* High registers used :7 (mp16uL,mp16uH,mc16uL/m16u0,mc16uH/m16u1,m16u2,
  269. ;* m16u3,mcnt16u)
  270. ;*
  271. ;***************************************************************************
  272.  
  273. ;***** Subroutine Register Variables
  274.  
  275. .def mc16uL =r16 ;multiplicand low byte
  276. .def mc16uH =r17 ;multiplicand high byte
  277. .def mp16uL =r18 ;multiplier low byte
  278. .def mp16uH =r19 ;multiplier high byte
  279. .def m16u0 =r18 ;result byte 0 (LSB)
  280. .def m16u1 =r19 ;result byte 1
  281. .def m16u2 =r20 ;result byte 2
  282. .def m16u3 =r21 ;result byte 3 (MSB)
  283. .def mcnt16u =r22 ;loop counter
  284.  
  285. ;***** Code
  286.  
  287. mpy16u: clr m16u3 ;clear 2 highest bytes of result
  288. clr m16u2
  289. ldi mcnt16u,16 ;init loop counter
  290. lsr mp16uH
  291. ror mp16uL
  292.  
  293. m16u_1: brcc noad8 ;if bit 0 of multiplier set
  294. add m16u2,mc16uL ;add multiplicand Low to byte 2 of res
  295. adc m16u3,mc16uH ;add multiplicand high to byte 3 of res
  296. noad8: ror m16u3 ;shift right result byte 3
  297. ror m16u2 ;rotate right result byte 2
  298. ror m16u1 ;rotate result byte 1 and multiplier High
  299. ror m16u0 ;rotate result byte 0 and multiplier Low
  300. dec mcnt16u ;decrement loop counter
  301. brne m16u_1 ;if not done, loop more
  302. ret
  303.  
  304. */
  305.  
  306.  
  307. ;***************************************************************************
  308. ;*
  309. ;* "bin2BCD16" - 16-bit Binary to BCD conversion
  310. ;*
  311. ;* This subroutine converts a 16-bit number (fbinH:fbinL) to a 5-digit
  312. ;* packed BCD number represented by 3 bytes (tBCD2:tBCD1:tBCD0).
  313. ;* MSD of the 5-digit number is placed in the lowermost nibble of tBCD2.
  314. ;*
  315. ;* Number of words :25
  316. ;* Number of cycles :751/768 (Min/Max)
  317. ;* Low registers used :3 (tBCD0,tBCD1,tBCD2)
  318. ;* High registers used :4(fbinL,fbinH,cnt16a,tmp16a)
  319. ;* Pointers used :Z
  320. ;*Courtesy of ATMEL
  321. ;***************************************************************************
  322.  
  323. ;***** Subroutine Register Variables
  324.  
  325. .equ AtBCD0 =13 ;address of tBCD0
  326. .equ AtBCD2 =15 ;address of tBCD1
  327.  
  328. .def tBCD0 =r13 ;BCD value digits 1 and 0
  329. .def tBCD1 =r14 ;BCD value digits 3 and 2
  330. .def tBCD2 =r15 ;BCD value digit 4
  331. .def fbinL =r16 ;binary value Low byte
  332. .def fbinH =r17 ;binary value High byte
  333. .def cnt16a =r18 ;loop counter
  334. .def tmp16a =r19 ;temporary value
  335.  
  336. ;***** Code
  337.  
  338. bin2BCD16:
  339. ldi cnt16a,16 ;Init loop counter
  340. clr tBCD2 ;clear result (3 bytes)
  341. clr tBCD1
  342. clr tBCD0
  343. clr ZH ;clear ZH (not needed for AT90Sxx0x)
  344. bBCDx_1:lsl fbinL ;shift input value
  345. rol fbinH ;through all bytes
  346. rol tBCD0 ;
  347. rol tBCD1
  348. rol tBCD2
  349. dec cnt16a ;decrement loop counter
  350. brne bBCDx_2 ;if counter not zero
  351. ret ; return
  352.  
  353. bBCDx_2:ldi r30,AtBCD2+1 ;Z points to result MSB + 1
  354. bBCDx_3:
  355. ld tmp16a,-Z ;get (Z) with pre-decrement
  356. ;----------------------------------------------------------------
  357. ;For AT90Sxx0x, substitute the above line with:
  358. ;
  359. ; dec ZL
  360. ; ld tmp16a,Z
  361. ;
  362. ;----------------------------------------------------------------
  363. subi tmp16a,-$03 ;add 0x03
  364. sbrc tmp16a,3 ;if bit 3 not clear
  365. st Z,tmp16a ; store back
  366. ld tmp16a,Z ;get (Z)
  367. subi tmp16a,-$30 ;add 0x30
  368. sbrc tmp16a,7 ;if bit 7 not clear
  369. st Z,tmp16a ; store back
  370. cpi ZL,AtBCD0 ;done all three?
  371. brne bBCDx_3 ;loop again if not
  372. rjmp bBCDx_1
  373.  
  374.  
  375.  
  376. ;**************
  377. ;Name: unpack2r4r0
  378. ;Desc: A subroutine to takes as input five (5) packed BCD digits, located
  379. ;      right justified, in the register combination r15:r14:r13.  The result
  380. ;      is fived unpacked BCD digits, placed in registers r0 through r4, in
  381. ;      ascending order
  382. ; Inputs: r15:r14:r13 (BCD4?BCD3BCD2?BCD1BCD0). Uppe nibble of r15 == 0000
  383. ; Outputs: r4: 0000 BCD4
  384. ;          r3: 0000 BCD3
  385. ;          r2: 0000 BCD2
  386. ;          r1: 0000 BCD1
  387. ;          r0: 0000 BCD0
  388. ; Alters: r0?r4, SREG,   ;* r10, r16
  389. ; calls: None
  390. ;*********************************************************************
  391. ;
  392.  
  393. unpack2r4r0:
  394. ldi r16, 0x0f ;load mask into r10 for future use
  395. mov r10, r16
  396. mov r4, r15 ;moves BCD4 and mask
  397. and r4, r10 ;upper nibble
  398. mov r2, r14 ;moves BCD2
  399. and r2, r10 ;mask BCD3
  400. mov r3, r14 ;move BCD3
  401. swap r3 ;swap to lower position
  402. and r3, r10 ;and mask upper nibble
  403. mov r0, r13 ;move BCD0 and
  404. and r0, r10 ;mask BCD1
  405. mov r1, r13 ;moves BCD1
  406. swap r1 ;swap to lower position
  407. and r1, r10 ;mask upper nibble
  408.  
  409.  
  410. ;**************
  411. ;Name: to_ascii_r9r5
  412. ;Desc: A subroutine to takes as input five (5) unpacked BCD digits, located
  413. ;      r0 to r4, and outputs the ascii equivalents to r5 to r9. The result
  414. ;      is fived unpacked BCD digits (r0..r4), directly followed by their
  415. ;      respective ascii equivalents in the next five registers (r5..r9).
  416. ;
  417. ; Inputs: r0 to r4 (unpacked BCD digits, with upper nibble == 0000)
  418. ;
  419. ; Outputs: r5 to r9 (ascii equivantlents to r0 to r4, respectively)
  420. ;
  421. ; Alters: r16, r9?r5, SREG
  422. ; calls: None
  423. ;*********************************************************************
  424.  
  425. to_ascii_r9r5:
  426. ldi r16, 0x30 ;r0 to ascii to r5
  427. or r16, r0
  428. mov r5, r16
  429.  
  430. ldi r16, 0x30 ;r1 to ascii to r6
  431. or r16, r1
  432. mov r6, r16
  433.  
  434. ldi r16, 0x30 ;r2 to ascii to r7
  435. or r16, r2
  436. mov r7, r16
  437.  
  438. ldi r16, 0x30 ;r3 to ascii to r8
  439. or r16, r3
  440. mov r8, r16
  441.  
  442. ldi r16, 0x30 ;r4 to ascii to r9
  443. or r16, r4
  444. mov r9, r16
  445. ret
  446.  
  447. ;*******************
  448. ; COURTESY OF SCOTT
  449. ;NAME: load_msg
  450. ;FUNCTION: Loads a predefined string msg into a specified diplay
  451. ; buffer.
  452. ;ASSUMES: Z = offset of message to be loaded. Msg format is
  453. ; defined below.
  454. ;RETURNS: nothing.
  455. ;MODIFIES: r16, Y, Z
  456. ;CALLS: nothing
  457. ;CALLED BY:
  458. ;********************************************************************
  459. ; Message structure:
  460. ; label: .db <buff num>, <text string/message>, <end of string>
  461. ;
  462. ; Message examples (also see Messages at the end of this file/module):
  463. ; msg_1: .db 1,"First Message ", 0 ; loads msg into buff 1, eom=0
  464. ; msg_2: .db 1,"Another message ", 0 ; loads msg into buff 1, eom=0
  465. ;
  466. ; Notes:
  467. ; a) The 1st number indicates which buffer to load (either 1, 2, or 3).
  468. ; b) The last number (zero) is an 'end of string' indicator.
  469. ; c) Y = ptr to disp_buffer
  470. ; Z = ptr to message (passed to subroutine)
  471. ;********************************************************************
  472. load_msg:
  473. ldi YH, high (dsp_buff_1) ; Load YH and YL as a pointer to 1st
  474. ldi YL, low (dsp_buff_1) ; byte of dsp_buff_1 (Note - assuming
  475. ; (dsp_buff_1 for now).
  476. lpm R16, Z+ ; get dsply buff number (1st byte of msg).
  477. cpi r16, 1 ; if equal to '1', ptr already setup.
  478. breq get_msg_byte ; jump and start message load.
  479. adiw YH:YL, 16 ; else set ptr to dsp buff 2.
  480. cpi r16, 2 ; if equal to '2', ptr now setup.
  481. breq get_msg_byte ; jump and start message load.
  482. adiw YH:YL, 16 ; else set ptr to dsp buff 2.
  483.  
  484. get_msg_byte:
  485. lpm R16, Z+ ; get next byte of msg and see if '0'.
  486. cpi R16, 0 ; if equal to '0', end of message reached.
  487. breq msg_loaded ; jump and stop message loading operation.
  488. st Y+, R16 ; else, store next byte of msg in buffer.
  489. rjmp get_msg_byte ; jump back and continue...
  490. msg_loaded:
  491. ret
  492.  
  493.  
  494.  
  495.  
  496. //Line messages
  497. line1_message: .db 1, "0.0000V ", 0 ; test string for line #1
  498. line2_message: .db 2, "----------------", 0 ; test string for line #2.
  499. line3_message: .db 3, " autorun", 0 ; test string for line #3.
  500. line4_message: .db 3, "Hold ", 0 ;String for when line 3 is on hold
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement