我正在尝试在MSP430G2553上实现一个温度传感器,用于读取和输出温度读数以及时间戳。基本要求如下:
•t:显示系统的当前时间。使用hhmmss格式输出到串行终端系统的当前时间,其中hh是24小时格式的两位数小时,mm是小时内的两位数分钟,ss是分钟内的两位数秒。
•s:设置系统的当前时间。将系统的当前时间设置为提供的参数。命令与其参数之间不会有空格。参数将在hhmmss表格中,其中hh是24小时格式的两位数小时,mm是小时内的两位数分钟,ss是分钟内的两位数秒。
•o:显示最旧的温度读数及其时间戳。向串行终端输出最旧的温度读数及其时间戳。输出必须具有hhmmss:T形式,其中hh是24小时格式的两位数小时,mm是小时内的两位数分钟,ss是分钟内的两位数秒,T是测量的温度。必须从列表中删除显示的条目。如果未执行读数,则必须显示“未记录温度”消息。
•l:显示所有温度读数及其时间戳。将所有温度读数及其时间戳输出到串行终端。输出应按时间顺序排列,最早的是。输出必须具有hhmmss:T形式,其中hh是24小时格式的两位数小时,mm是小时内的两位数分钟,ss是分钟内的两位数秒,T是测量的温度。必须从列表中删除所有条目。如果未执行读数,则必须显示“未记录温度”消息。 您的系统还必须满足以下要求:
•您必须每隔五(5)分钟捕获一个新的温度读数,并至少存储32个温度读数。如果已达到最大温度读数,请在存储新温度之前丢弃最旧的温度读数。
输入't'2次后发生错误。下次输入't'时,它输出3或4个垃圾值。当我注释掉's'的情况或者将's'更改为另一个变量时,我在switch语句中的't'情况运行得非常好,但是对于赋值的情况需要在情况's'输入到uart中。到目前为止我所尝试的内容包括:更改变量,注释掉第二种情况,更改S案例的值以确保垃圾值是由于这种情况导致的,使用包围某些代码部分,修改了t的整个第一部分效率更高,但仍然出现相同的错误等。任何建议都会非常有帮助。 Picture of Garbage Values
#include "msp430g2553.h"
volatile short unsigned int i=0,j=0,k=0;//This the integer that track the number of cycles
volatile short unsigned int timercount=0;//This the integer that track the number of cycles
volatile unsigned int GT=2600;//variable that sets the global time in seconds of the system
volatile char inputcharacters[16];//Input character storage array
volatile unsigned int tempature[32];//
volatile unsigned int tempaturetime[32];
volatile unsigned int d[6]={0,0,0,0,0,0},test[7];
volatile unsigned int h=0;
volatile unsigned int m=0;
volatile unsigned int ss=0;
int temp=0;
void main(void)
{
WDTCTL = WDTPW + WDTHOLD;//Disabling watchdogtimer
P1DIR |= BIT0;//setting p1 bit 1 to outy
P1OUT &= ~BIT0;//Shutting off the LED
/* UART config for 9600 baud with SMCLK*/
IE2 = 0x00;//interrupts off on UART
UCA0CTL1 = 0x81;//using SMCLK(1Mhz) and software reset enable
UCA0CTL0 = 0x00;//eight data bits, no parity, one stop bit
UCA0MCTL = 0x02;//Setting UCBRSx to 1 to set clock rate to 9600
UCA0BR0 = 0x68;//set clock rate to 9600 from 1Mhz
UCA0BR1 = 0x00;//set clock rate to 9600
UCA0STAT = 0x00;//error check and parity, and frame error check all off
TACTL = 0x1D0;// sets timer a to use the 32.768kh clock with 8 divisor and in up mode
TACCR0 = 0x1001;// setting the timer to count up to 4097 to get a 1hz(1s) oscillation
TACCTL0 &= 0xFFEF;// disable capture compare interrupts
P1SEL|=0X06;// According to slas735j both p1.1(0X02) and p1.2(0X04) need to be set on to receive and send on the UART
P1SEL2|=0X06;
ADC10CTL0 &= ENC;
ADC10CTL0 = SREF_1 | ADC10SHT_3 | REFON | ADC10ON;
ADC10CTL1 = INCH_10 | ADC10DIV_2 | ADC10SSEL_3;
//ADC10CTL0 = 0x3030;
//ADC10CTL1 = 0xA038;
ADC10CTL0 &= 0xFFFC;
/* Enable USCI logic and Enable interrupts */
UCA0CTL1 &= 0xFE;//turning on USCI logic
IE2 = 0x01;// Sets UART to receive interrupt
TACCTL0 = CCIE;// set timerA interupts on done last
__bis_SR_register(LPM3_bits + GIE);//found on TI wiki
}
#pragma vector=USCIAB0RX_VECTOR// This vector name was pulled from the webcources code
__interrupt void uartinput(void)//this form found on TI's wiki
{
inputcharacters[i] = UCA0RXBUF;
UCA0TXBUF = UCA0RXBUF;
if((i>14)||(inputcharacters[i]=='\r'))
{if(inputcharacters[i]=='\r'){inputcharacters[i]=0;}//to reduce i, the number of inputs so that we dont count the \r
for(j=0;j<i;j++){switch(inputcharacters[j]) {//switch statement that check the input characters and outputs the correct morse
case 't' :
h=GT/3600;
m=(GT-h*3600)/60;
ss=GT-h*3600-m*60;
d[0]=(h/10);
d[1]=(h-(d[0]*10));
d[2]=(m/10);
d[3]=(m-(d[2]*10));
d[4]=(ss/10);
d[5]=(ss-(d[4]*10));
for(k=0;k<6;k++)
{while((IFG2 & 0x02)==0)
{;}
UCA0TXBUF=d[k]+48;
test[k]=d[k]+48;}
while((IFG2 & 0x02)==0)
{;}
UCA0TXBUF='\r';
break;
case 'x' ://If this break case is not set to 's' it will not cause the error in the 't' case, no idea why
GT=0;
temp=(inputcharacters[j+1]-0x30)*10;//
temp+=(inputcharacters[j+2]-0x30);
GT+=(temp*3600);
temp=(inputcharacters[j+3]-0x30)*10;
temp+=(inputcharacters[j+4]-0x30);
GT+=(temp*60);
temp=(inputcharacters[j+5]-0x30)*10;
temp+=(inputcharacters[j+6]-0x30);
GT+=temp;
j+=7;
break;
case 'o' :
{;}
break;
case 'l' :
{;}
break;
case '\r' :
{;}
break;
default :
{i++;}
}}
i=0;
j=0;
}
else{i++;}}
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_interupt(void)
{
if(GT<86459)//24:00:59 in seconds
{GT++;}//add a second
else
{GT=60;}//00:01:00
if(timercount<299)//300s=5min
{timercount++;}
else{timercount=0;
ADC10CTL0 |= 0x3;// turn on ADC
while(ADC10CTL1 & ADC10BUSY)//loop to alow for ADC to finish sampeling
{;;}
ADC10CTL0 & 0xFFFE;//Shuting off the ADC after sampeling
tempature[i]=ADC10MEM;//Storing the tempature
tempaturetime[i]=GT;// storing the time
if(i<31)
{i++;}
else
{i=0;}
}
}
答案 0 :(得分:0)
发布代码的一个非常明显的问题是,当发现当前正在检查的输入字符为x
时,必须在用户输入{{1}后输入新的日期戳(作为6位数)但是在用户输入x
之前,这可以使用,但是没有代码强制执行该输入序列。
一般来说,uart输入函数应该包含几个状态和子状态&#39;其中命令char导致代码切换到“状态”状态。那将有实际时间戳的子状态。所以当用户输入一个命令时,如\r
一个模式被设置,输入的下一个6位是新的时间戳。
建议设计一个对语境敏感的&#39;状态图然后实现该图。
除此之外,输入缓冲区的大小将减少到1个字节
在许多排序问题中,有一个事实是,当积累一些数字时,说出像这样的事情x
不会产生预期的结果。
将产生预期结果的是:
int temp = 0;
temp += inputchar[x] - 0x30;
temp += inputchar[x+1] - 0x30;
...
当然,在尝试将该输入应用于int temp = 0;
temp += inputchar[x] - 0x30;
temp = temp*10 + (inputchar[x+1] - 0x30);
....
temp = temp*10 + (inputchar[x+5] - 0x30);
GT = temp;
为了便于开发,强烈建议一次只尝试实现一个命令以及该命令何时正常工作(大量使用调试器使测试变得容易。例如temp
调试器芯片。)然后转到下一个要执行的命令。
在两个中断处理程序中都修改了变量jtag
。因此,当一个中断处理程序修改i
时,另一个中断的值就会被破坏。
一整天(24小时)是878400秒,因此值86459不正确。此外,这是一个魔术&#39;代码中的数字。神奇的数字没有基础。 &#39;魔术&#39;数字使代码更难以理解,调试和维护。建议使用i
声明或enum
声明来提供“魔法”#39;编号一个有意义的名称,然后在整个代码中使用有意义的名称。注意:将#define
计数器重置为60是不正确的,在发布的代码中应将其重置为0.
“魔法”也存在类似的考虑因素。 300号。
当输入命令为GT
时,发布的代码没有动作,因此我们无法分析此类(不存在的)代码以确定它有什么问题。
处理l
命令:
t
变量可能会在访问之间进行修改。建议保存到新的&#39;变量并从该新变量中进行所有计算。
GT
,h
和m
的计算正在对相同的中间变量进行大量重新计算。建议:
s
数组int myGT = GT;
h = myGT / 3600;
myGT %= 3600;
m = myGT / 60;
s = myGT % 60;
已设置但未使用。这是生产代码中的资源浪费。建议其&#39;存在和设置由一些test[]
编译器参数确定。