简体   繁体   中英

Thermostat in assembly language

I cant get this project to run. Not sure what else to do. This code is part of an assembly language program for the MSP430 microcontroller. It sets up the stack, stops the watchdog timer, sets the clock divider, initializes registers, sets pins for LED control, sets up the ADC10 for temperature sensor readings, stores readings, gets previous readings, sets up an array, sets up a timer interrupt, and adds interrupt service and vector routines. The program is designed to measure and store temperature readings, and then control two LEDs based on the readings. The LEDs will be turned on or off depending on the temperature thresholds set in the code.

#include "msp430.h"                     ; #define controlled include file
NAME    main 

PUBLIC  main

ORG     0F800h
; Constants for LED control
LED1_ON EQU 0x01 ; Turns on LED1
LED1_OFF EQU 0x00 ; Turns off LED1
LED2_ON EQU 0x01 ; Turns on LED2
LED2_OFF EQU 0x00 ; Turns off LED2

; Temperature thresholds
LOWEST_TEMP EQU 56 ; Lowest temperature that turns on LED1
COOL_ROOM_TEMP EQU 68 ; Cool room temperature that turns on LED1 and LED2
ROOM_TEMP EQU 72 ; Room temperature that turns on LED1 and LED2
HOT_ROOM_TEMP EQU 78 ; Hot room temperature that turns on LED1 and LED2
HIGHEST_TEMP EQU 90 ; Highest temperature that turns on LED2

;Setup for Array
_byte   EQU 1
temp_array  DS (_byte * 32)  ; 16-bit 32 element array






init: ; Set up the stack and stop the watchdog timer
      MOV.W #0280h, SP
      MOV.W #WDTPW+WDTHOLD,&WDTCTL
      BIS.B #DIVS_3,&BCSCTL2 ; Set the clock divider to SMCLK/8
      MOV.W #0000h, R14 
      MOV.W #0000h, R4 
      MOV.W R15, 0 ; Initialize the location to 0
      ADD.W R15, 1 ; Increment the location to store the reading at the next index


setupP1: ; Set P1.0 to output for LED1 control
        BIS.B #001h, &P1DIR

; Set P2.0 to output for LED2 control
setupP2: 
        BIS.B #001h, &P2DIR

; Set up the ADC10 for temperature sensor readings
SetupADC10 
           mov.w #INCH_10+ADC10DIV_3,&ADC10CTL1 ; Temp Sensor ADC10CLK/4
           mov.w   #SREF_1+ADC10SHT_3+REFON+ADC10ON+ADC10IE,&ADC10CTL0 ;
      
      BIS.W #GIE,SR ; Enable interrupts
main:
      NOP
      CALL #get_previous_reading ; Check the temperature every 2 minutes by calling get_previous_reading
      CALL #SetupArray ; Set up the array to store the temperature readings
      CALL #SetupTimer ; Set up the timer to generate interrupts every 30 seconds

store_reading:
MOV.W &ADC10MEM, temp_array(R15);
ADD.W R15, 1
ret


get_previous_reading:
MOV.W R15, R5
SUB.W R5, 120 ; Subtract 120 to get the temperature reading 2 minutes ago
MOV.W temp_array(R5), R5 ; Return the temperature reading from that location in the array
ret

SetupArray:
MOV.W #0, temp_array ; Initialize the array to store the temperature readings
MOV.W #0, R15 ; Initialize the current location in the array to 0
ret

SetupTimer:
MOV.W #CCIE,&CCTL0 ; CCR0 interrupt enabled
MOV.W #30*1000,&CCR0 ; Generate an interrupt every 30 seconds
ret

;-------------------------------------------------------------------------------
;           Interrupt Service Routines
;------------------------------------------------------------------------------- 
ADC10_ISR:
        call store_reading
        reti


;-------------------------------------------------------------------------------
;           Interrupt Vectors
;-------------------------------------------------------------------------------
        ORG     0FFFEh
        DC16    init                    ; set reset vector to 'init' label
        ORG     0FFEAh                  ; ADC10 interrupt vector
        DW      ADC10_ISR  
        END

These are the Errors i get Mon Dec 12, 2022 14:20:18: Warning: A word access on odd address 0x1

I haven't used this assembly language before, but there are many assembly languages that work in a similar way. The warning "Word access on odd address 0x1" typically means that your code is attempting to read a 16-bit value from an unaligned address. Here's what you need to change:

ADD.W R15, 1; Increment the location to store the reading at the next index

This needs to become ADD.W R15,2 . Unlike C, assembly does not automatically scale your pointer arithmetic. The CPU doesn't know that R15 is being used as a pointer, so you'll need to add 2 to avoid overwriting half the previous value. This might not be enough to remove the warning, however, since most assemblers can only warn you about unaligned access at compile time.

Next let's take a look at main :

main:
      NOP
      CALL #get_previous_reading ; Check the temperature every 2 minutes by calling get_previous_reading
      CALL #SetupArray ; Set up the array to store the temperature readings
      CALL #SetupTimer ; Set up the timer to generate interrupts every 30 seconds

store_reading:
MOV.W &ADC10MEM, temp_array(R15);
ADD.W R15, 1
ret

In assembly, a function label is not a form of control flow. To put this into perspective here's some C code:

int main()
{

}

void store_reading(void)
{

}

The curly braces do more than just visually separate your functions. They automatically have the necessary control flow commands to exit the function properly. This is a level of abstraction that doesn't exist in assembly; an assembly "function" needs to be told to ret or loop infinitely, or else whatever is underneath will automatically execute. Assembly is similar in control flow to BASIC, where the program begins at a specified entry point and whatever the next instruction is, will be run, unless the program counter is altered with jumps, calls, returns, etc.

To make your program work as intended, you'll want to set up everything before you go to main , and just have main loop forever (since your interrupt will run every 30 seconds no matter what main is doing.

The only other issue I can see is your array indexing out of bounds, which it will do after r15 increments past the size of your array. That's an easy fix, thankfully. Your array is 16 words in size, so if you bitwise AND R15 with the constant value 15, your array index will wrap around back to zero and you'll never be out of bounds. Yes, you'll overwrite the old entries, but you don't need to remember the temperature that long ago anyway.

store_reading:
MOV.W &ADC10MEM,temp_array(R15);
ADD.W R15,1
AND.W R15,15
RET

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM