注册 登录  
 加关注
查看详情
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

一车,一房,一个温暖家

10万左右的车,80平方的房子,这是我奋斗的暖暖的家

 
 
 

日志

 
 

引用 上位机与单片机的互动之移植(四)   

2015-03-22 14:53:51|  分类: 默认分类 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

今天是3月22号,进度有点慢,

已完成进度:

1、完成基本人机界面。

上位机与单片机的互动之移植(四) - 静水深流 -

 

2、完成人机界面与单片机通信。

3、完成自定协议的移植(稍有变化)。

自定协议:

数据域(N)字节、命令(1字节)、地址(1字节)、校验码(2字节)

4、数据帧通信成功(包括CRC验证)。 待完成进度:

1、上位机指定电机PWM值与方向,并正确执行相应方向,PWM。

2、车速监控(包括左,右电机PWM值监控)。

3、规范代码。

 

 

C语言代码如下:

#include<STC12C5410AD.h>
#include<CRC16.h>
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long

/*电机状态定义*/
#define  MotorDrv P2   //电机驱动IO口
//左侧电机定义
#define  ML_FORWARD 0x02  //电机正转
#define  ML_BACK  0x04  //电机反转
#define  ML_FLOAT 0x06  //电机惰行, 此时停止PWM输出
#define  ML_BRAKE 0x00  //电机刹车
#define  ML_REMOVE 0xF8  //清除左侧电机状态
//右侧电机定义
#define  MR_FORWARD 0x20  //电机正转
#define  MR_BACK  0x40  //电机反转
#define  MR_FLOAT 0x60  //电机惰行, 此时停止PWM输出
#define  MR_BRAKE 0x00  //电机刹车
#define  MR_REMOVE 0x8F  //清除右电机状态

//接收数据定义
uchar ga_ucRcvBuf[4]; //接收数据寄存器
uchar gc_uCount;  //接收计数器
bit g_bRcvCount;  //接收完毕标志
bit g_bCheckRcvData; //数据正确性标志

/********************************************/
/* 名称:init_SIO       */
/* 用途:初始化串口,       */
/* 参数: 波特率 , 模式固定为:1     */
/*   1 START 8 DATA 1 STOP     */
/********************************************/
uchar text;
void init_SIO()
{
 TMOD = TMOD|0x20|0x00;   //设定T1为定时器模式
 PCON = 0;
 AUXR = AUXR|0x00;   //Set 12T
 SCON = SCON|0x40|0x10;  
 TH1 = 0xFA;
 TL1 = 0xFA;
 TR1 = 1;
 EA = 1;
 ES = 1;

}

void delay_1ms(uchar a)
{
 uchar x,y;
 for(x = a;x > 0;x--)
 {
  for(y = 220;y > 0;y--);
 }
}
/********************************************************************
* 名称 : checkData()
* 功能 : 检测接收到的数据是否正确?
* 输入 : 无
* 输出 : g_bCheckRcvData(返回1则为数据正确)
*********************************************************************/
bit checkData(void)
{
 ulong g_ulCrcLow;   //存储计算后的低位CRC
 ulong g_ulCrcHigh;   //存储计算后的高位CRC
 uchar g_ucRcvCrcLow;  //暂储接收到的低位CRC
 uchar g_ucRcvCrcHigh;  //暂储接收到的高位CRC
 uchar g_uCrcHigh;
 if(ga_ucRcvBuf[2] == 0x10)
 {
  g_ucRcvCrcLow = ga_ucRcvBuf[0];
  g_ucRcvCrcHigh = ga_ucRcvBuf[1];
  ga_ucRcvBuf[0] = 0;
  ga_ucRcvBuf[1] = 0;
  g_ulCrcLow = cal_crc(ga_ucRcvBuf,5);
  g_ulCrcLow = g_ulCrcLow & 0xFF;
  if(g_ucRcvCrcLow == g_ulCrcLow)
  {
   g_ulCrcHigh = cal_crc(ga_ucRcvBuf,5);
   g_ulCrcHigh = g_ulCrcHigh >> 8;
   g_uCrcHigh = g_ulCrcHigh;
   if(g_ucRcvCrcHigh == g_uCrcHigh)
   { 
   //这里可以处理校验成功后的功能
   //这里为单片机接收到正确指令后给上位机回应
    g_bCheckRcvData = 1; //表明接收数据正确
   }
  }else
  {g_bCheckRcvData = 0;}
 }
 return g_bCheckRcvData;
}


/*驱动电机*/
void motorDrive(uchar ML_Motor,uchar MR_Motor)  
{
 MotorDrv = 0x00;   //复位P2口为0000 0000
 MotorDrv |= ML_Motor;  //左侧电机状态
 MotorDrv |= MR_Motor;  //右侧电机状态
}

/*PWM输出参数设置*/
void pwmOutput(uchar mModeAdd,uchar PWM_CEX,uchar cuCycle) 
{
 uchar ucCexCl,ucCexCh;
 ucCexCh = cuCycle * 2.55;  //根据占空比计算比较值
 ucCexCl = ucCexCh;
 switch(mModeAdd)       //检测模块地址
 {
  case 0:       
  {
   CCAPM0 = PWM_CEX;
   CCAP0L = ucCexCl;
   CCAP0H = ucCexCh;
   break;
  }
  case 1:
  {
   CCAPM1 = PWM_CEX;
   CCAP1L = ucCexCl;
   CCAP1H = ucCexCh;
   break;
  }
  case 2:
  {
   CCAPM2 = PWM_CEX;
   CCAP2L = ucCexCl;
   CCAP2H = ucCexCh;
   break;
  }
  case 3:
  {
   CCAPM3 = PWM_CEX;
   CCAP3L = ucCexCl;
   CCAP3H = ucCexCh;
   break;
  }
  default: break;
 } 
}

/********************************************************************
* 名称 : Com_Int()
* 功能 : 串口中断子函数
* 输入 : 无
* 输出 : 无
***********************************************************************/
void comInt() interrupt 4 using 3
{
 EA = 0;
 if(RI == 1)   //当硬件接收到一个数据时,RI会置位
 {
  RI = 0;
  /***************************成功
  ga_ucRcvBuf[0] = SBUF;
  Delay_1ms(1);
  ************************/
  ga_ucRcvBuf[gc_uCount] = SBUF;
  gc_uCount ++;
  if(gc_uCount > 4)
  {
   gc_uCount = 0;
   g_bRcvCount = 1;
  }
 }
 if(TI == 1)
 {
  TI = 0;
 }
 EA = 1;
}

void main()
{
 gc_uCount = 0;
 g_bRcvCount = 0;   //接收数据计数器
 text = 0;
 P2M0 = 0x00;      //将P20,P24设置成强推挽输出
 P2M1 = 0x01;
 CMOD |= 0x02;      ////PCA模式寄存器,Fosc/2
 CL = 0x00;
 CH = 0x00;
 init_SIO();   //波特率为9600
 while(1)
 {
  if(g_bRcvCount == 1)
  {
   g_bRcvCount = 0;
   EA = 0;
   text = ga_ucRcvBuf[4];
   if(checkData())    //数据正确性检测
   {
    SBUF = ga_ucRcvBuf[4];
    g_bCheckRcvData = 0;  //将数据判断器复位
    motorDrive(ML_FORWARD,MR_FORWARD);
    pwmOutput(2,0x42,50);
    CR = 1;
   }
   EA = 1;
  }
  delay_1ms(1);
 }
}

VB代码如下:

Private Sub Command1_Click(Index As Integer)
        If MSComm1.PortOpen = False Then
        On Error GoTo cntOpenCom
        If Combo1.Text = "COM1" Then
            MSComm1.CommPort = 1
        ElseIf Combo1.Text = "COM2" Then
            MSComm1.CommPort = 2
        ElseIf Combo1.Text = "COM3" Then
            MSComm1.CommPort = 3
        ElseIf Combo1.Text = "COM4" Then
            MSComm1.CommPort = 4
        ElseIf Combo1.Text = "COM5" Then
            MSComm1.CommPort = 5
        ElseIf Combo1.Text = "COM6" Then
            MSComm1.CommPort = 6
        ElseIf Combo1.Text = "COM7" Then
            MSComm1.CommPort = 7
        End If
        MSComm1.PortOpen = True
         MsgBox ("串口打开完毕!")
    Else
        MsgBox ("串口已打开!")
cntOpenCom:
        MsgBox ("错误描述:" & Err.Description)
    End If
End Sub

Private Sub Command2_Click()
    If MSComm1.PortOpen = False Then
        MsgBox ("串口未打开!")
    Else
        MSComm1.PortOpen = False
        MsgBox ("串口关闭成功!")
    End If
End Sub

'可用CRC校验码
Function bCRC(data() As Byte, le As Byte) As Long
'数组指针计数器
    Dim mc_bPtr As Byte
'unsigned char i;
    Dim i As Byte
'unsigned int crc=0;
    Dim crc As Long
    crc = 0
    mc_bPtr = 0
                            '<--------CRC计算入口
    Do While (le <> 0)
    le = le - 1
'for(i=0x80; i!=0; i/=2)
        Dim c As Byte       '模拟i=0x80
        c = &H80
        For i = 0 To 7
            If ((crc And &H8000) <> 0) Then
                crc = crc And &H7FFF
                crc = CLng(crc) * 2
                crc = CLng(crc) Xor &H1021
            Else
                crc = CLng(crc) * 2
            End If
            If ((data(mc_bPtr) And c) <> 0) Then
                crc = CLng(crc) Xor &H1021
            Else
            End If
            c = c / 2
         Next
             mc_bPtr = mc_bPtr + 1
    Loop
'return(crc);
    bCRC = CLng(crc)
End Function

Private Sub Command3_Click()        '输出电机的PWM与方向命令
    Dim sende(0 To 4) As Byte
    Dim g_lcrcLow As Byte
    Dim g_lcrcHigh As Byte
    Dim ccrc As Long
    sende(0) = &H0
    sende(1) = &H0
    sende(2) = &H10
    sende(3) = &H90
    sende(4) = &HA
    g_lcrcLow = bCRC(sende, 5) And &HFF
    g_lcrcHigh = bCRC(sende, 5) \ 256
    sende(1) = g_lcrcHigh
    sende(0) = g_lcrcLow
   ' Print "LOW=" & g_lcrcHigh
    ' Print "HIGH=" & sende(4)
     MSComm1.Output = sende
End Sub

Private Sub Form_Load()
  Combo1.ListIndex = 5    '设置COM口选项默认值
    Timer1.Enabled = False
    MSComm1.InBufferSize = 40 '初始化串口
    MSComm1.InBufferCount = 0
    MSComm1.InputMode = comInputModeBinary '二进制方式
    MSComm1.CommPort = 1
    MSComm1.Settings = "9600,N,8,1"
    MSComm1.RThreshold = 1
    MSComm1.InputLen = Val(Combo1.Text)
End Sub

Private Sub MSComm1_OnComm()
    If MSComm1.CommEvent = comEvReceive Then
        Text4.Text = AscB(MSComm1.Input)
    End If
End Sub

  评论这张
 
阅读(7)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018