我爱嵌入式系统

当前位置:首页 > 软件天地 > 业内资讯 > 详细内容
驱动器主机机485通讯
发布时间:2009/11/13  阅读次数:4499  字体大小: 【】 【】【

/*----------------------------------------------------------------------
功能描述:驱动器主机机485通讯 -通讯速率4800bps-用于测试485总线
本程序realease版本在avr开发板“05-4-28 by hank”上面运行

PC5 = 1--发送允许控制脚
--------------------------------- --------------------------------------

------------------------------------------------------------------------ */  
/*------------------------------------------------------------------------
一共6个字节
第一个字节始终为0xAA,它作为帧头以用来标识一个数据帧的起始;
第二个字节为地址字节,用来标识这个数据包的目的CPU(当数据包是
       主控制CPU 发出时)或者是源CPU(当数据包是从控制CPU发出时);
第三个字节为命令字节;
第四个字节为校验字节,其作为整个帧的校验(累加和校验);
第五和第六字节为数据字节,其为这一个数据包中与命令有关的有效数据。
------------------------------------------------------------------------*/
#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>
#include <inttypes.h>
//#include "LCD.h"

#define COM_ADD       01//从机地址

#define UART_CTRL_PORT    PORTA
#define UART_CTRL_DDR      DDRA
#define UART_CTRL_NUM      PA7

#define tx485en()        UART_CTRL_PORT |= (1<<UART_CTRL_NUM) //发送
#define rx485en()        UART_CTRL_PORT &= ~(1<<UART_CTRL_NUM) //接收
uint8_t char_txbuf[6];                                   //串行通信的缓冲区
uint8_t char_rxbuf[6];
uint8_t TX_js, RX_js;          //字节个数计数
uint8_t RX_bz, TX_bz;              //帧接受完毕标志


SIGNAL(SIG_UART_RECV)
{
      
       for(RX_js = 0; RX_js<5; RX_js++)
       char_rxbuf[RX_js] = char_rxbuf[RX_js+1];
       char_rxbuf[5] = UDR;
  //接收的字节首先存到数组末尾,5次循环后帧头0xAA就处于首位
       if((char_rxbuf[0] == 0xaa)&&(char_rxbuf[1] == COM_ADD)
    &&((uint8_t)((char_rxbuf[2]+char_rxbuf[4]+char_rxbuf[5]))
    ==char_rxbuf[3]))       //检查校验码)
             RX_bz = 1;
  //帧接受完毕标志,
      
}
SIGNAL(SIG_UART_TRANS)
{
      
       if(TX_js<6)
  {
       UDR = char_txbuf[TX_js];
       TX_js++;
  }
  else {
                       TX_bz = 0;//串口发送忙标志清零
                 rx485en();
                     }
}
//启动发送,并传出第一个数据
void UART_Putchar(void)
{
       TX_bz = 1;             //串口发送忙标志
       tx485en();
       UDR = char_txbuf[0];
  TX_js = 1;
}

//不使能电机
void motor_no(void)
{
  char_txbuf[0] = 0xaa;
  char_txbuf[1] = COM_ADD;
  char_txbuf[2] = 0;
  char_txbuf[4] = 0;
  char_txbuf[5] = 0;
  char_txbuf[3] = (uint8_t) (char_txbuf[2] + char_txbuf[4] + char_txbuf[5]);
  UART_Putchar();
  while(TX_bz != 0);
}
//使能电机
void motor_yes(void)
{
  char_txbuf[0] = 0xaa;
  char_txbuf[1] = COM_ADD;
  char_txbuf[2] = 1;
  char_txbuf[4] = 0;
  char_txbuf[5] = 0;
  char_txbuf[3] = (uint8_t) (char_txbuf[2] + char_txbuf[4] + char_txbuf[5]);
  UART_Putchar();
  while(TX_bz != 0);
}
/*---------------------------------------------------
设置步进电机的增量转角和方向
n增量步数,0~180°对应n=0~96*20(1920),这儿n是8位字节,
但每次增量步数不要超过255,便于传输,也防止转向过急
d=0反转       d=1正转     设定电机转动方向
---------------------------------------------------*/
void stepper_ctrl(uint8_t n, uint8_t d)
{
  char_txbuf[0] = 0xaa;
  char_txbuf[1] = COM_ADD;
  char_txbuf[2] = 2;
  char_txbuf[4] = n;
  char_txbuf[5] = d;
  char_txbuf[3] = (uint8_t) (char_txbuf[2] + char_txbuf[4] + char_txbuf[5]);
  UART_Putchar();
  while(TX_bz != 0);
}
/*---------------------------------------------------
设置直流电机的速度和方向
n 速度等级0~30,PID的运算周期1s
d=0反转       d=1正转     设定电机转动方向
---------------------------------------------------*/
void dcmotor_ctrl(uint8_t n, uint8_t d)
{
  char_txbuf[0] = 0xaa;
  char_txbuf[1] = COM_ADD;
  char_txbuf[2] = 3;
  char_txbuf[4] = n;
  char_txbuf[5] = d;
  char_txbuf[3] = (uint8_t) (char_txbuf[2] + char_txbuf[4] + char_txbuf[5]);
  UART_Putchar();
  while(TX_bz != 0);
}
/*---------------------------------------------------
查询步进电机的目前绝对转角记录steps=0~1920(假设不丢步)
复位值steps 为1920/2
---------------------------------------------------*/
uint16_t angle_inquire(void)
{
  char_txbuf[0] = 0xaa;
  char_txbuf[1] = COM_ADD;
  char_txbuf[2] = 4;
  char_txbuf[4] = 0;
  char_txbuf[5] = 0;
  char_txbuf[3] = (uint8_t) (char_txbuf[2] + char_txbuf[4] + char_txbuf[5]);
  UART_Putchar();
  while(TX_bz != 0);
  while(RX_bz == 0);
  return( (((uint16_t)char_rxbuf[4]) << 8) + (uint16_t)char_rxbuf[5] );
}
/*---------------------------------------------------
5.  case 5: 查询直流电机速度参数Vsam=0~30
---------------------------------------------------*/
uint8_t vel_inquire(void)
{
  char_txbuf[0] = 0xaa;
  char_txbuf[1] = COM_ADD;
  char_txbuf[2] = 5;
  char_txbuf[4] = 0;
  char_txbuf[5] = 0;
  char_txbuf[3] = (uint8_t) (char_txbuf[2] + char_txbuf[4] + char_txbuf[5]);
  UART_Putchar();
  while(TX_bz != 0);
  while(RX_bz == 0);
  return(char_rxbuf[4]);
}

static void avr_init(void)
{
       // Initialize device here.
  //485初始化接收状态
  UART_CTRL_DDR |= 1<<UART_CTRL_NUM;
  rx485en();
  RX_bz = 0;
  TX_bz = 0;
         //uart初始化
  //4800bps,8个数据位,1个停止位,无奇偶校验,异步正常模式
  //接收使能、发送使能、接收中断允许、发送中断允许
  //UCSRA和UCSRC采用默认值
    UCSRB=(1<<RXCIE)|(1<<TXCIE)|(1<<RXEN)|(1<<TXEN);  
  UBRRL=51;  // baud=4800     UBRR=CK/(baud*16) -1  
      
       return;
}

int main(void)
{
  unsigned int i;
       avr_init();
       sei();
      
  //PC7-LED, PC6-KEY,使能上拉电阻
  DDRC = (1<<DDC7) | (0<<DDC6);
  PORTC = (0<<PC7) | (1<<PC6);
  
/*------------------------------------------------   
  //测试步进电机专用
  while(1)
  {
    while(bit_is_set(PINC, PC6));  
    motor_yes();
    for(i=6000; i>0; i--);    
    while(bit_is_clear(PINC, PC6));
    while(bit_is_set(PINC, PC6));  
    
    stepper_ctrl(250, 1);    
    for(i=6000; i>0; i--);    
    while(bit_is_clear(PINC, PC6));
    while(bit_is_set(PINC, PC6));  
    
    stepper_ctrl(250, 1);    
    for(i=6000; i>0; i--);    
    while(bit_is_clear(PINC, PC6));
    while(bit_is_set(PINC, PC6));
    
    stepper_ctrl(250, 1);    
    for(i=6000; i>0; i--);    
    while(bit_is_clear(PINC, PC6));
    while(bit_is_set(PINC, PC6));
    
    stepper_ctrl(250, 1);    
    for(i=6000; i>0; i--);    
    while(bit_is_clear(PINC, PC6));
    while(bit_is_set(PINC, PC6));
    
    motor_no();
    for(i=6000; i>0; i--);    
    while(bit_is_clear(PINC, PC6));    
    while(bit_is_set(PINC, PC6));  
    
  }
  ------------------------------------------------*/  
//  测试各个功能,5种命令,2005-7-18
  while(1)
  {
    while(bit_is_set(PINC, PC6));  
    motor_yes();
    for(i=6000; i>0; i--);    
    while(bit_is_clear(PINC, PC6));
    while(bit_is_set(PINC, PC6));  
    
    stepper_ctrl(250, 1);    
    for(i=6000; i>0; i--);    
    while(bit_is_clear(PINC, PC6));
    while(bit_is_set(PINC, PC6));  
    
    dcmotor_ctrl(10, 1);
    for(i=6000; i>0; i--);    
    while(bit_is_clear(PINC, PC6));
    while(bit_is_set(PINC, PC6));  
    
    angle_inquire();
    for(i=6000; i>0; i--);    
    while(bit_is_clear(PINC, PC6));
    while(bit_is_set(PINC, PC6));  
    
    vel_inquire();
    for(i=6000; i>0; i--);    
    while(bit_is_clear(PINC, PC6));
    while(bit_is_set(PINC, PC6));  
    
    motor_no();
    for(i=6000; i>0; i--);    
    while(bit_is_clear(PINC, PC6));    
    while(bit_is_set(PINC, PC6));  
    
  }
    
   /*------------------------------------------------
   给从机发命令测试程序,按键一次发命令一次,循环执行,led闪烁指示系统正常工作
   2005.7.18调试通过
  
  unsigned char addr=0;
   while(1)
   {
    if(bit_is_clear(PINC, PC6))
    {
      char_txbuf[0] = 0xaa;
      char_txbuf[1] = COM_ADD;
      char_txbuf[2] = addr;
      char_txbuf[4] = 6;
      char_txbuf[5] = 0;
      char_txbuf[3] = (uint8_t) (char_txbuf[2] + char_txbuf[4] + char_txbuf[5]);
      UART_Putchar();
      while(TX_bz != 0);
      addr += 1;
      if(addr > 5)
        addr = 0;
      while(bit_is_clear(PINC, PC6));  
    }
    
     PORTC |= (1 << PC7);
     for(i=6000; i>0; i--);
      
    PORTC &= ~(1 << PC7);
    for(i=6000; i>0; i--);
   }
       ------------------------------------------------*/
       return(0);
}

我要评论
  • 匿名发表
  • [添加到收藏夹]
  • 发表评论:(匿名发表无需登录,已登录用户可直接发表。) 登录状态:未登录
最新评论
所有评论[0]
    暂无已审核评论!

51RTOS.com 版权所有  

Copyright 20006-2009 我爱嵌入式 ( 51RTOS.com ) All rights reserved 沪ICP备09080633号