⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scanner.c

📁 msp430例程
💻 C
字号:
//********************采集机程序**************************************
//name:  scanner.c    
//******************************************************************************
//输出管脚说明:
// P3.6 tx_en 当开始发送一帧时使能,当一帧发送完毕后禁止。软件上,在SendByte子函使能,在发送中断$的处理部分进行
//******************************************************************************

#include  <msp430x13x.h>
#include  "scanner.h"
         
void main(void)
{ 
  unsigned int k=0;
  unsigned int i=0;
  
  unsigned char tmp,tmp1;
  P4OUT = 0X00;
  P4DIR = 0XFF;   //强制输出低电平,防止继电器闭合
  P5OUT = 0X00;
  P5DIR = 0XFF;  

  //上电后给运放一个输入,防止输出过高。
  P1DIR = 0XFF;                        
  P2DIR = 0X0F;   
  P3DIR = 0xDB;                        // P3.5,P3.2为输入  
  
  P1OUT = 0X00;
  P2OUT = 0X00; 
  P3OUT = 0X18;         //同时禁止发送,防止个别没有复位的单板拉死总线,防止继电器闭合,点灯

  WDTCTL = WDTPW + WDTCNTCL;    //clear wdt       WDTCTL = WDTPW + WDTHOLD;     // Stop watchdog timer  
  
  for(i=0;i<10;i++)
  {
    P3OUT ^= 0x02;                
    DelayAMoment();
  }  
  
   //-----系统基础时钟初始化--------  
   //从内部振荡器切换到外部8M的晶振,切换不成功时靠硬件狗复位
  BCSCTL1 &= ~XT2OFF;
  do 
  {
    IFG1 &= ~OFIFG;                       // Clear OSCFault flag
    for (i = 0xFF; i > 0; i--);           // Time for flag to set
  } while ((IFG1 & OFIFG) == OFIFG);      // OSCFault flag still set?         
  BCSCTL2|= SELM1 + SELS;                 //选择外部晶振,MCLK=8Mhz SMCLK=8Mh
  
  //------初始化TimerA--------------
  //该定时器用于在自检中的超时定时,保证自检中某些操作在硬件不正常时能够超时返回
  TACTL = TASSEL1 + TACLR +ID0+ID1;     // SMCLK, 8DIV =1M;clear TAR, UP TO CCR0 MODE
                                        // 
  CCTL0 = CCIE;                         // CCR0 interrupt enabled
  CCR0 = 50000;                         // 50ms 中断一次
  TACTL |= MC0;                         // Start Timer_A in up mode  
                           

  //-----系统自检,覆盖到大部分硬件的可用性-------------
//  if(SelfTest()== 0)                   //系统自检测试
//  SelfTest();
  
  //------系统软硬件资源初始化---------------
  InitSys();                    //初始化系统硬件资源和软件资源
  
  //------读取本板ID号,若没有则置为00------
  ptrFlashData = (char *)IDADDRESS;   
  
  if((*ptrFlashData) == 0x55)
  {
    ptrFlashData--;
    m_IDL = *ptrFlashData;
    ptrFlashData--;
    m_IDH = *ptrFlashData;
  }
  else
  { 
    m_IDH = 00;
    m_IDL =0x0;
  }
  
  //  
  WDTCTL = WDTPW + WDTCNTCL;    //clear wdt    
  
  //------主循环----------
  for (;;)                      //主循环        
  {  
    //这部分代码的作用是,对18路电池电压分别采集1024次,取均值,
    //假设一次AD转换需要15us,则大约需要15*18*1024=276ms完成一次扫描。计工频周期,干扰很小  
    //*****************************************************************
    if(ScanInitRes)
    {                   
        ScanInitRes = FALSE;      //清楚初始化采集请求
        
        //bypass 发送的命令采集:m_ResID = 0x99;
        //bypass 处于bypass采集状态:scanres = 1, m_resid =0, m_residbuf = 0x99;
        //其他发送的采集命令:m_ResID!=0x99
        //处于其他发送的采集状态:scanres =1,m_resid=0,m_residbuf!=0x99
        //现在暂时不区分采集状态,仅判断采集命令的发出者和目的,设定一个低优先级,m_ResID=0x99,其他
        //  优先级的采集命令都可以中断当前的采集任务,处于主动采集的查询状态时,m_residBuf = 0x88,这一点暂仅用于上传数据响应中。
        
        if(ScanRes&&(m_ResID==0x99))   //当bypass功能发送采集请求,但已经处于采集状态时
        {
               //已经清除采集请求,直接退出
        }
        else if(OwnScanReady)    //若有主动采集的数据时,等待一秒再开始下一次采集
        {          
            if(OwnScanReady == 0x55)
            {            
              OwnScanReady = FALSE;
            }
            else
            {
              OwnScanReady = 0x55;
            }
        }              
        else 
        {
            if(ScanRes&&(m_ResID!=0x99)) //当是其他模块发送的采集请求,但此时已经采集状态时
            {                
                while(!(ADC12IFG & ADC12BUSY)); //等待转换完成后,不理睬数据,直接重新置变量
                
//                ADC12CTL0 &= &ENC;      //停止当前的采集,丢弃数据
            }
            
            //上述语句中不甚严谨,应再判断是否是bypass的状态,若不是则不应中断,但当前考虑不会有此情况,故以下语句也先省略
            
//            if(m_ResID==0x99)
  //          {
    //           m_ResIDbuf = 0x99;    //当是bypass发送的采集请求时,将Buf也置为99,标志进入bypas采集状态
      //      }
            m_ResID = 0x00;         //将m_ResID置0            
            
//            ta =0;          //使时钟同步,这样单板看起来比较整齐,步调一致
            k = 0;
            ChAdder = 0;
//            m_TotalChannelCur = 0;   //通道电压之和
            ChNum = 0;            
             
            ADC12CTL0 |= ENC;                     // Enable conversions        
    
            ScanRes = TRUE;           //要求进行一次电池电压采集
            ptrFlashData = (char *)P1DATAADDRESS;  //存储P1OUTDATA的地址
            P1OUT = *ptrFlashData;    //P1OUTDATA[0];                 //设置4051通道  
            ptrFlashData = (char *)P2DATAADDRESS+ChNum;  //存储p2outdata的地址
            P2OUT = *ptrFlashData;          
                 
            //读取CH1的采集增益
            ChTimes = DEFAULTTIMES;         //读取设定的增益      
            if(ReadPara(2))
            {
                ChTimes = FlashPara;
            }
    
            ptrFlashData  +=35;   //指向本通道的零点存储位置;
            tmp = *ptrFlashData;                            //times的值放在FLASH中,地址从TIMESADDRESS开始
            ptrFlashData++;
            tmp1 = *ptrFlashData;
            if((tmp == 0xff) &&(tmp1 == 0xff))              //当无效时
            {
                ChZero = 0x00;  //DEFAULTTIMES;                               //默认值
            }
            else
            {
                ChZero = (unsigned int)(tmp&0x0f)*100+tmp1;
                if(tmp&0xe0)                                  //若高位为1,则为负数,这是自定义的负数格式,尽量遵守了常用方法
                {
                    ChZero = -ChZero;
                }
                ChZero = ChZero*100;  //对于2048次的和,此值需要放大100倍,否则没有效果
            }                                   
    
            ADC12CTL0 |= ADC12SC;               // Start conversion            

            for(tmp=0;tmp<18;tmp++)             //保存上一次采集到的电压值
            {
                m_ChannelHis2[tmp] = m_ChannelCur[tmp];
            }
            
        }           
        
    }
    //**************************
    if(k>4000)k = 1;      //此处限定K值不大于4000,大于4000可能造成异常。
    
    if(ScanRes == TRUE&&((ADC12IFG & ADC12BUSY)== 1)) //当使能了一次采集  且转换已经完成后
    {
        if(k<= ChTimes)           //当尚未达到本通道采集数目时
        {
            ChAdder += ADC12MEM0;        //累加  CHNUM 从0~17对应第1~18通道
            ADC12CTL0 |= ADC12SC;               // Start conversion  ,同时启动采样,
            k++;
        }        
  
        else
        {
            ChAdder = ChAdder+ChZero;   //调整零点            
            ChAdder += 512;      //四舍五入    
            ChAdder = ChAdder/1024;          //为了仅使用两字节通讯,牺牲了部分精度,最完美的做法是将1024次采集的结果全部读出
            if(ChAdder>0xfe00){ChAdder = 0;};  //当无电压输入时,消除负零点电压的影响

            m_ChannelCur[ChNum] = ChAdder;                       

//            m_TotalChannelCur += ChAdder;     //计算总电压,当前仅有主动采集功能使用,但我认为会有其他功能使用,故放在此处
           
            ChNum++;      //采集下一个通道
            k = 0;
            
            if(ChNum < 18)
            {            
                ptrFlashData = (char *)P1DATAADDRESS+ChNum;  //存储P1OUTDATA的地址
                P1OUT = *ptrFlashData;    //P1OUTDATA[0];                 //设置4051通道  
                ptrFlashData = (char *)P2DATAADDRESS+ChNum;  //存储p2outdata的地址
                P2OUT = *ptrFlashData;          
            
                ChTimes = DEFAULTTIMES;         //读取设定的增益      
                if(ReadPara(2*(ChNum+1)))
                {
                    ChTimes = FlashPara;
                }
                
                ptrFlashData  +=35;   //指向本通道的零点存储位置;
                tmp = *ptrFlashData;                            //times的值放在FLASH中,地址从TIMESADDRESS开始
                ptrFlashData++;
                tmp1 = *ptrFlashData;
                if((tmp == 0xff) &&(tmp1 == 0xff))              //当无效时
                {
                  ChZero = 0x00;  //DEFAULTTIMES;                               //默认值
                }
                else
                {
                  ChZero = (unsigned int)(tmp&0x0f)*100+tmp1;
                  if(tmp&0xe0)                                  //若高位为1,则为负数,这是自定义的负数格式,尽量遵守了常用方法
                  {
                      ChZero = -ChZero;
                  }
                  ChZero = ChZero*100;
                }                
                
                //debug03041    
                P3OUT ^= 0x02;          
                 
                Delay1ms();                         //用于避免通道间的干扰,使4051的输出可靠建立

                ADC12CTL0 |= ADC12SC;               // Start conversion                    
            }
            else    //当完成全部18个通道的采集时
            {                                   
                ScanRes = FALSE;
                ADC12CTL0 &= ~ENC;                  // Disable conversions                   
                m_ResID = m_ResIDbuf;     //刷新命令ID,以使上位机确认是最新的数

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -