MSP430G2333下位机乘法运算需要注意的一个问题

背景:

  最近负责为主板管理电源的电源管理模块编写软体,使用的MCU为MSP430G2333。功能上很简单,即通过板子上的硬件拨码设定,或者通过IIC与主板通信,由主板的BIOS决定开机及关机的延时供电时间。

正文:

  所有功能均按预期实现,但有一个bug在最后蹦了出来,即在延时关机设定时,明明设定为15、18、48个小时,却每次在9个多小时的时候,电源被执行关闭动作。9个多小时,很有意思的数字。不用深究,问题直接锁定在时间比对函数内。

 1 // when the current time less than the setting time, return 0. Otherwize, return 1.
 2 char compare_timer(unsigned char h, unsigned char m, unsigned char s)
 3 {
 4     unsigned long TimerCnt     = 0;
 5     unsigned long TimerSetCnt = 0;
 6     unsigned char i;
 7
 8         // timer_s, timer_m, timer_h are increased in the 1s timer interrupt
 9         TimerCnt = timer_h*3600  + timer_m*60 + timer_s;
10
11         TimerSetCnt = h*3600 + m*60 + s;
12
13
14     if(TimerCnt >= TimerSetCnt) {
15           return 0;    //time is out
16     }
17     else {
18           return 1;
19     }
20 }    

  根据现象,首先考虑的是溢出问题,TimerCnt 为“unsigned long”型,以最久48个小时来算,也就172800,远小于4个字节的存量。排除!

  或许是中间变量存储问题,于是将代码更改如下(部分)

TimerCnt += timer_h*3600
TimerCnt += timer_m*60
TimerCnt += timer_s; 

TimerSetCnt += h*3600
TimerSetCnt += m*60
TimerSetCnt += s; 

  结果然并卵。排除!

  前面说过,9个多少小时,9*3600 = 32400,很微妙的数字。65535(0xFFFF) / 2 = 32767,差不多相等。于是,想到了乘法寄存器的问题。

  此处,虽说保存结果的位置给了四个字节空间(“unsigned long TimerCnt”),但是在做乘法运算的时候,运算结果会放在乘法结果寄存器,由以上现象可知,乘法结果寄存器最大存放2个字节,其中最高位还得预留给符号位,所以其最大的值为32767(0x7FFF)。改正代码如下:

  

/* 不再使用 TimerCnt = timer_h*3600 是因为其乘法结果会溢出
 * 其实本可以有更漂亮的解决办法,但是Rom(4k)不够用了 T_T ···只能这么写
 */
for(i = 0; i < timer_h; i++)
{
    TimerCnt += 3600;
}
TimerCnt += timer_m*60;
TimerCnt +=    timer_s;        

  至此,总结完毕!下次在下位机的时候,一定要注意不能再犯!

记录地点:深圳WZ

记录时间: 2016年2月29日 (四年一次,有意义~ : ) )

  

时间: 2024-10-22 16:48:41

MSP430G2333下位机乘法运算需要注意的一个问题的相关文章

下位机单片机c语言发送数据到串口,上位机pc机java语言获取端口数据

环境: Windows7 64b,jdk64b,myeclipse8.5,rxtx开发包,STC,keil,格西烽火,51单片机,rs232USB转串口线. 下位机c代码 #include <reg51.h> #include <string.h> #define INBUF_LEN 7   //数据长度 unsigned char inbuf1[INBUF_LEN]; unsigned char checksum,count3,count=0; bit           rea

6.PMAC下位机-下位机编程

PMAC的下位机编程包括三种程序:命令序列程序.运动(Program)程序和PLC程序. PMAC中编写程序,直接在File->new新建文件会打开编辑器,所有文件为PMC后缀. 查看当前程序可以在File->Uplaod Programs查看当前已有的Program程序和PLC程序及他们的编号.状态. 1.命令序列程序 上节讲到,PMAC卡中可以使用手动操作,在命令行设置参数状态.控制电机等,但是它一次只能发送一条命令,那么为了一次性运行多个命令序列,即可在PMC程序中如下编写: i620=

串口操作包括 java上位机 嵌入式c下位机

一环境 1.1 Keil uVision4 http://pan.baidu.com/s/1o6A331w 1.2 STC http://pan.baidu.com/s/1jGpCUTC 1.3 Myeclipse 8.5 http://pan.baidu.com/s/1jGABEaM 1.4 需导入的jar包RXTX http://pan.baidu.com/s/1ntwsvRr 首先把rxtxParallel.dll和rxtxSerial.dll复制到jdk目录的bin目录下面 然后把RXT

4.PMAC下位机-工具安装和使用

PMAC应该看成一台独立的电脑,它有自己的实时操作系统,为了更方便简单的使用,PMAC有自己的一套操作语言来对PMAC的输入输出信号进行控制(IO.电机等信号).和大多数的嵌入式开发一样,PMAC提供一套PC工具来方便查看PMAC控制卡的各种状态变量和编写.调试PMAC程序. 本文介绍PMAC配套工具PEWin32(这里推荐使用PEWin32 PRO,不推荐使用PEWin32 PRO 2,这个新版本有很多bug且不稳定),下一节介绍下位机相关知识,再下一节讲PMAC的下位机编程,这些都是在pew

局域网控制系统-下位机-单片机

1 /*----------------------------------- 2 多功能下位机 3 STC89C52RC 11.0592MHz 4 5 -----------------------------------*/ 6 #include<reg52.h> 7 #include<intrins.h> 8 9 char code huanhang[3]={0x0d,0x0a,0}; // "\r\n" 10 //-----------------普通输

5.PMAC下位机-下位机编程简介

PMAC的下位机编程涉及三方面的内容:手动操作.运动(Program)程序和PLC程序.这里主要是介绍各个方面的基础编程方面的东西,还有许多需要自行去探索. 变量 PMAC的下位机实际上是一种类Basic的编程语言,但是又类似汇编语言,所有变量的存储空间都是预先分配好的,操作的时候存储数据只能在指定的几种变量类型和变量名中存储,整个系统的参数也是存储在变量中. 变量类型和作用如下: I变量:卡,电机和编码器等的参数变量,用于设置电机的速度,精度,回零等数值,以及坐标系的状态,编码器的反馈形式,P

12.PMAC上位机-中断通信(下位机通知上位机)

之前说过,上位机控制硬件都是通过发送指令进行的,这是单向的.那么反过来,下位机硬件给上位机发送指令怎么才能实现呢?对于PMAC来说,最常见的情况就是,当PMAC一次运动完成时通知当前PC程序运动已完成. 1.下位机通知上位机原理 如下图所示, PC给PMAC发送指令控制它做什么,当运动程序完成后中断通知上位机,在中断的同时发送一个标识P100表明完成的程序号,这个标明到底是1号轴运动完,还是是2号轴运动完.在PC端有一个中断回调函数,下位机发送中断后,会自动跳转到该函数中,中断函数接受中断,根据

C# 连蒙带骗不知所以然的搞定USB下位机读写

原文:C# 连蒙带骗不知所以然的搞定USB下位机读写 公司用了一台发卡机,usb接口,半双工,给了个dll,不支持线程操作,使得UI线程老卡. 懊恼了,想自己直接通过usb读写,各种百度,然后是无数的坑,最终搞定. 现将各种坑和我自己的某些猜想记录一下,也供各位参考. 一.常量定义 private const short INVALID_HANDLE_VALUE = -1; private const uint GENERIC_READ = 0x80000000; private const u

5.23-ROSARIA下位机使用

前言 基础:下位机配置 前言使用记录环境搭建基础:ssh使用基础:netcat基础:secureCRT(多标签ssh)后续工作 TOC 使用记录 环境搭建 sudo apt-get install libsdl1.2-dev libsdl-image1.2-dev sudo apt-get install ros-indigo-move-base 配置激光ip地址:192.168.0.4 mask:192.168.0.0 gateway:192.168.0.1 安装其他库,编译文件代码 /Ros