EDN首页   博客首页

最新日志

发表于:2009/6/3 17:14:36
标签:vista  mdk  

1

【转帖】MDK在VISTA下注册的问题

转自:http://www.embedinfo.com
问题描述: 在VISTA环境下注册MDK的时候,提示“ERROR R206:NO REGISTRY ACCESS,ADMINISTRATION RIGHTS REQUIRED”
问题解答: 在VISTA系统上管理员权限默认是关闭的,请在桌面快捷图标Keil uVision3处点击右键——>使用管理员权限打开MDK,然后再进行LIC的注册

系统分类: ARM   |    用户分类:    |    来源: 转贴

该用户于2009/6/3 17:15:17编辑过该文章

评论(0) | 阅读(94)
发表于:2009/5/26 9:05:16
标签:STM32  ISP  UART  

1

[转载]调通STM32的串口ISP的经验,可从以下几方面入手:

 

1、Boot0需接高(注意不要超过3.6V,非5V容忍脚),Boot1(PB2)需接低(电阻下拉或直接接地)。

2、VDDA/VSSA一定要接好,电压符合要求(2.4~3.6V).即使不用ADC也要接,因为VDDA还为POR/OSC/PLL等“模拟”部分供电。

3、检查复位脚的电位是否正常,JTAG仿真器有可能复位系统。

4、检查TXD/RXD信号通路。当然要畅通,呵呵。

5、如果用非mcuisp的软件,最好在TXD/RXD上加上拉电阻到MAX232电源,防止产生干扰信号。mcuisp从软件上处理了这个干扰,可不考虑这点。

6、波特率先设为9600bps,调通后再提高到115200。波特率是否能跑高,与PC串口(USB串口线)、MAX232质量有关。

 

A:检查RXD通路的方法:用eagleCom打开串口后,点击流控线一页的"<-3V Normal Txd"按钮,可变成“>+3V Break”。如此,可用万用表测量stm32的PA10/UART1_RX,看其电平是否随eagleCom端控制而变化。eagleCom显示"<-3V Normal Txd"时,PC的DB9的3脚应该是负电压,MAX232输出则为高电平;eagleCom显示“>+3V Break”时,PC的DB9的3脚应该是正电压,MAX232输出为低电平。

 

B:检查TXD通路的方法:eagleCom设置为9600bps,8数据位,Even校验,1StopBit,定时10ms发送0x7F字符(选中\hh HEX转换后输入\7F),此时应该接收到0x79或0x1F。如不通,用万用表测量PA9/UART1_TX-->MAX232-->PC的DB9的2脚,检查那里有问题。

 

www.mcuisp.com 单片机在线编程网版权所有 转载请注明出处

系统分类: ARM   |    用户分类:    |    来源: 转贴

该用户于2009/5/26 9:05:40编辑过该文章

评论(0) | 阅读(155)
发表于:2009/4/18 15:04:42
标签:HT1380  AVR  C  驱动程序  

1

【原创】HT1380 AVR C语言驱动程序

#include "ht1380.h"

/*************短时间延时***********************************/
void dly_HT1380(void)
{
 asm("nop");
 asm("nop");
 asm("nop");
 asm("nop");
}

/*************向HT1380中写一个字节*************************/
void HT1380_write(uint8_t data)
{
 uint8_t i="0";
 set_HT1380_io_ddr();
 clr_HT1380_io();
 for(i=8;i>0;i--)
 {
  dly_HT1380();
  if(data&0x01)
  {
   set_HT1380_io();
  }
  dly_HT1380();
  set_HT1380_sclk();
  dly_HT1380(); 
  clr_HT1380_sclk();
  dly_HT1380(); 
  clr_HT1380_io();
  data>>=1;
 }
}

/*************从HT1380中读一个字节*************************/
int HT1380_read(void)
{
 uint8_t data="0";
 uint8_t i="0";
 clr_HT1380_io_ddr();//让io变成输入
 for(i=8;i>0;i--)
 {
  set_HT1380_sclk();
  dly_HT1380();
  data >>= 1;   
  if(in_HT1380_io())
  {
   data |= 0x80;
  }
  else
  {
   data &= 0x07f;
  }
  clr_HT1380_sclk();
  dly_HT1380();
 } 
 return(data);
}

/**********从HT1380中读日期和时间******************************/
void HT1380_read_time(void)
{
 clr_HT1380_sclk();
 set_HT1380_io_ddr();
 clr_HT1380_rst();
 dly_HT1380();
 set_HT1380_rst(); //
 HT1380_write(0xbf); 
 dly_HT1380();
 clr_HT1380_io_ddr();
 dly_HT1380();
 second=HT1380_read(); //秒
 minute=HT1380_read(); //分
 hour=HT1380_read(); //时
 day=HT1380_read(); //日
 month=HT1380_read();//月
 week=HT1380_read(); //周
 year=HT1380_read(); //年
 dly_HT1380();
 clr_HT1380_rst();
}
/**********向HT1380写日期和时间******************************/
void HT1380_write_time(void)
{
 clr_HT1380_sclk();
 set_HT1380_io_ddr();
 clr_HT1380_rst();
 dly_HT1380();
 set_HT1380_rst(); //
 HT1380_write(0x8e);
 HT1380_write(0x00);  
 dly_HT1380();
 clr_HT1380_rst();
 dly_HT1380();
 set_HT1380_rst(); //
 HT1380_write(0x80);
 HT1380_write(0x00);
 dly_HT1380();
 clr_HT1380_rst();
 dly_HT1380();
 set_HT1380_rst(); //
 HT1380_write(0xbe);
 HT1380_write(second); // 秒
 HT1380_write(minute); //分
 HT1380_write(hour); //时
 HT1380_write(day); //日
 HT1380_write(month); //月
 HT1380_write(week); //周
 HT1380_write(year); //年
 HT1380_write(0x00);  
 dly_HT1380();
 clr_HT1380_rst();
}

rar

系统分类: 单片机   |    用户分类:    |    来源: 原创

该用户于2009/4/18 15:05:01编辑过该文章

评论(1) | 阅读(358)
发表于:2009/3/26 10:55:41
标签:无标签

3

关于博客上发表原创、假冒原创、转帖文章的观点

  • 我的观点很鲜明原创必须支持!假冒原创必须打击!但是转帖也是允许。
    关于原创和假冒原创我同意HOTPOWER大侠的观点,我就不多说了。详见:
    http://www.dianyuan.com/wangping/ti/blog_article_view.php?blar_id=424#a357

    http://www.dianyuan.com/wangping/ti/blog_article_view.php?blar_id=422

    我说点关于转帖的看法。我发现很多初学者都比较心急,都喜欢一次把资料找齐,而作者呢并不是每一个方面都精通,所以很难在一个人的博客里找齐所有需要的资料。为了方便别人也为了方便自己,转帖一些其它人的东西查找起来比较方便,所以说转帖也是应该允许的。呵呵...好象是废话

  • 系统分类: 自由话题   |    用户分类:    |    来源: 原创

    该用户于2009/3/26 10:55:52编辑过该文章

    评论(2) | 阅读(441)
    发表于:2009/3/14 8:44:35
    标签:STM32  示波器  USB2.0  

    3

    【转帖】我的毕设总结-用STM32的高速AD和USB2.0做简易示波器

    转自:21ic  作者:fmj2008

    今天是3月9号,再过3个月就要大学毕业了,最近工作找得郁闷。干脆躲回实验室,总结下我的毕业设计,算是把自己的大学画个句号吧。

    1 概述
    毕业设计的题目是“基于STM32的简易示波器设备驱动的研究”,就是利用STM32的AD采集波形数据,然后通过它内置的USB2.0把数据传到PC上面显示出来。框图如下:
    点击开大图

    题目一共是两个人做,我和我搭档耗子。他做信号处理,采集部分。我做USB在PC下的驱动开发,以及上位机界面的显示。USB固件那部分我们是一起完成的。
      这个课题从08年10月开始,到12月圣诞前夕基本完成。最后基本实现了波形的显示,实测最大可以测量的频率是200KHZ,
    效果图如下:

    点击开大图


    方波的图形好像不是很漂亮会有上升沿老是有尖刺,还需要作软件做处理。没截出来,
      最后能出数据离不开很多前辈的经验。有些地方是借鉴了他们的东西。现在先列出来。
    第一个是21IC上面alien2006原帖地址。他也是做了一个简易示波器,但是用的是以太网传输。采集部分我很多借鉴了他的方案。
    第二个是电脑圈圈,他对USB的理解令我钦佩。我能搞出驱动,他提供的源码包非常重要,有些代码也是直接在他的基础上修改的。

    2 整体方案
      先说下一次完整的采集,比如外面进来的波形是正弦波,波形电压有正负,STM32单片机的AD只能采集0~3.6V的电压,所以要对信号进行处理。也就是需要一个模拟前端电路,把电压抬上去。接着就是采集了,STM32的AD可以用外设进行触发,这里用定时器进行触发。每过一个单位时间AD开启一次,采集一个点,这样采集的频率只要调整这个单位时间也就是定时器就可以控制了。采集了一桢数据,比如200个点。DMA中断被触发,开启USB,把数据发送到上位机,然后显示出来。
      整个过程大体就是这样了,还有一个很重要的环节补充下。熟悉示波器的人都知道示波器有个触发概念。像刚才这样显示的话,比如前一帧数据是波峰开始显示,后一帧是波谷开始。这样显示出来的波形就是乱的,于是为了解决这个问题,就需要做触发,也就是保证每次采集的起始电位相同。我们的采用的是用外中断的形式,外面波形数据先不采集,先让它通过一个比较器,比如比较器的基准电压是1V,也就是每次都和1V比较,低于1V输出低电平,高于1V输出高电平。当数据电压大于1V的时候,比较器输出高电平,高电平接到单片机外中断口,这样外中断就被触发。然后开始采集,这样就能保证每帧数据的起始点都相同。
      这个方案是大体方案,后来做了下修改。就是让AD一直在采集。外中断触发了后开启的是DMA,AD一直开着,只是控制DMA什么时候去取。从哪里开始取,取多少个点。下位机部分不再详说,贴下主要的程序,大侠们随便看看,多多指教。
    定时器设置代码如下:
    /*******************************************************************************
    * Function Name  : TIM_Configuration
    * Description    : Configure the TIM2.
    *******************************************************************************/
    void TIM2_Configuration(void)
    {
      TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
      TIM_OCInitTypeDef  TIM_OCInitStructure;
       
      TIM_DeInit(TIM2); //TIM2初始化
         
      /* Time base configuration */
      TIM_TimeBaseStructure.TIM_Period = 18; //设置了下一个更新事件装入活动的自动重装载寄存器周期的值
      TIM_TimeBaseStructure.TIM_Prescaler = 0; //设置了用来作为TIMx时钟频率除数的预分频值
      TIM_TimeBaseStructure.TIM_ClockDivision = 0;  //设置了时钟分割
      TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //选择了计数器模式向上计数

      TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);  //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx

      /* Prescaler configuration */
    //  TIM_PrescalerConfig(TIM2, 1, TIM_PSCReloadMode_Update); //设置TIMx重载次数 预分频值在更新事件装入
      
      /* TIM_OCMode_Toggle Mode configuration: Channel2 */
      TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;           
      TIM_OCInitStructure.TIM_Channel = TIM_Channel_2;           
      TIM_OCInitStructure.TIM_Pulse = 9;   
      TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;  //TIM输出比较极性低
         
      TIM_OCInit(TIM2, &TIM_OCInitStructure);
       
      TIM_ARRPreloadConfig(TIM2, ENABLE); //使能或者失能TIMx在ARR上的自动装载寄存器
       
      /* TIM2 enable counter */
      TIM_Cmd(TIM2, ENABLE); //使能TIMx外设
    }
    AD以及DMA设置代码:
    /*******************************************************************************
    * Function Name  : ADC_Configuration
    * Description    : Configure the ADC1.
    *******************************************************************************/
    void ADC_Configuration(void)
    {
      /* DMA channel1 configuration ----------------------------------------------*/
      DMA_DeInit(DMA_Channel1); //复位DMA_Channel1
      DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; //外围设备地址
      DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADC_Data[0]; //memory 地址
      DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //外围设备做为源
      DMA_InitStructure.DMA_BufferSize = 1024;  //数据单元尺寸
      DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  //外围地址是否自动增长 disable不增长
      DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //memory 是否自动增长
      DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //外围设备寄存器尺寸16位
      DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;  //memory尺寸16位
      DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;  //DMA 循环模式
      DMA_InitStructure.DMA_Priority = DMA_Priority_High;  //DMA 通道优先级
      DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //memory- to-memory转换
      DMA_Init(DMA_Channel1, &DMA_InitStructure);  //初始化DMA通道1

      /* DMA IT enable */
      DMA_ITConfig(DMA_Channel1, DMA_IT_TC, ENABLE); //使能DMA传输完成中断
      
      /* ADC1 configuration ------------------------------------------------------*/                                                      
      ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;  //ADC 工作模式 ADC1 ADC2 单独工作     
      ADC_InitStructure.ADC_ScanConvMode = DISABLE;  //多通道扫描模式
      ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //是否启用连续转换模式
      ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC2;  //触发方式
      ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;   //数据右对齐
      ADC_InitStructure.ADC_NbrOfChannel = 1;  //ADC规则转换通道数量
      ADC_Init(ADC1, &ADC_InitStructure);

      /* ADC1 regular channel10 configuration */ //配置转换规则
      ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_1Cycles5);
       
      /* Enable ADC1 DMA */
      ADC_DMACmd(ADC1, ENABLE);

      /* Enable ADC1 */
      ADC_Cmd(ADC1, ENABLE);

      /* Enable ADC1 reset calibaration register */
      ADC_ResetCalibration(ADC1);  //复位ADC1 校准
      /* Check the end of ADC1 reset calibration register */
      while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位完成

      /* Start ADC1 calibaration */
      ADC_StartCalibration(ADC1);  //开始ADC1 校准转换
      /* Check the end of ADC1 calibration */
      while(ADC_GetCalibrationStatus(ADC1));  //等待转换完成
       
      ADC_ExternalTrigConvCmd( ADC1, ENABLE); //使能或者失能ADCx的经外部触发启动转换功能
    }

    DMA中断服务程序:
    /*******************************************************************************
    * Function Name  : DMAChannel1_IRQHandler
    * Description    : This function handles DMA Stream 1 interrupt request.
    *******************************************************************************/
    void DMAChannel1_IRQHandler(void)
    {
      DMA_Cmd(DMA_Channel1, DISABLE);  //关闭DMA通道1
      for(count=64;count<1024;count++)  //AD数据转换处理
      {
        AD_Data[count]=(ADC_Data[count]*330)/4096;
      }
      flag_usb = 1;  //usb标志位置1,使能usb发送
      DMA_ClearITPendingBit(DMA_IT_TC1);
    }

      下面就开始说我做的部分,USB部分。一共有3个地方,
    (1)USB固件程序的开发
    (2)Windows XP下USB设备驱动的开发
    (3)对应的PC上的应用程序开发。
    下面来详细论述。

    3  USB固件程序的开发
      这部分主要设计USB的协议。一共花了两个星期时间,是我们做的最开心的两个星期。因为是两个人一起来研究,导师崔也经常跑过来讨论。最后测出来的传输速度是700-800K,依据USB2.0全速理论最大速度12Mbps,除以八大概是1M多,基本把速度都开发出来了。期间参考了ouravr里面的一个叫极速狂飙的帖子,也成功开启了双缓冲。
      固件程序主要是根据万利板子提供的4个USB程序中的那个USB转串程序修改的,主要是修改两个文件。第一个是usb_desc.c,这个文件里面配置了全部的描述符。这些描述符在USB2.0协议里面都有严格的定义,跟着配置就好了。
    const u8 Virtual_Com_Port_DeviceDescriptor[] =
      {
        0x12,   /* bLength */
        USB_DEVICE_DESCRIPTOR_TYPE,     /* bDescriptorType */
        0x00,
        0x02,   /* bcdUSB = 2.00 USB2.0版本*/
        0xFF,   /* bDeviceClass:  USB分配的设备类*/
        0xFF,   /* bDeviceSubClass 子类*/
        0x00,   /* bDeviceProtocol */
        0x40,   /* bMaxPacketSize0 端点0最大包大小*/
        0x44,
        0x44,   /* idVendor = 0x4444 高位在后*/
        0x33,
        0x33,   /* idProduct = 0x3333 */
        0x00,
        0x02,   /* bcdDevice = 2.00 */
        1,              /* Index of string descriptor describing manufacturer */
        2,              /* Index of string descriptor describing product */
        3,              /* Index of string descriptor describing the device's serial number */
        0x01    /* bNumConfigurations */
      };

    const u8 Virtual_Com_Port_ConfigDescriptor[] =
      {
        /*Configuation Descriptor配置描述符*/
        0x09,   /* bLength: Configuation Descriptor size */
        USB_CONFIGURATION_DESCRIPTOR_TYPE,      /* bDescriptorType: Configuration */
        VIRTUAL_COM_PORT_SIZ_CONFIG_DESC,       /* wTotalLength:no of returned bytes */
        0x00,
        0x01,   /* bNumInterfaces: 1 interface 此配置所支持的接口数量*/
        0x01,   /* bConfigurationValue: Configuration value */
        0x00,   /* iConfiguration: Index of string descriptor describing the configuration */
        0xC0,   /* bmAttributes: self powered 自供电*/
        0x00,   /* MaxPower 0 mA 设备从总线提取的电流*/
        /* 9 */
               
        /*Data class Interface Descriptor接口描述符*/
        0x09,   /* bLength: Endpoint Descriptor size */
        USB_INTERFACE_DESCRIPTOR_TYPE,  /* bDescriptorType: */
        0x00,   /* bInterfaceNumber: Number of Interface 该接口编号0为基*/
        0x00,   /* bAlternateSetting: Alternate setting */
        0x02,   /* bNumEndpoints: 该使用的端点数*/
        0xFF,   /* bInterfaceClass:  接口类型*/
        0xFF,   /* bInterfaceSubClass: 子类 */
        0x00,   /* bInterfaceProtocol: 接口遵循的协议*/
        0x00,   /* iInterface: 描述该接口字符串索引*/
        /* 18 */
         
        /*Endpoint 3 Descriptor*/
        0x07,   /* bLength: Endpoint Descriptor size */
        USB_ENDPOINT_DESCRIPTOR_TYPE,   /* bDescriptorType: Endpoint */
        0x03,   /* bEndpointAddress: (OUT3) */
        0x02,   /* bmAttributes: Bulk */
        0x02,    
        0x00,   /* PacketSize: */
        0x00,   /* bInterval: ignore for Bulk transfer */
         
        /*Endpoint 1 Descriptor*/
        0x07,   /* bLength: Endpoint Descriptor size */
        USB_ENDPOINT_DESCRIPTOR_TYPE,   /* bDescriptorType: Endpoint */
        0x81,   /* bEndpointAddress: (IN1) */
        0x02,   /* bmAttributes: Bulk */              
        0x40,    
        0x00,   /* wMaxPacketSize:批量传输最大包 64byte*/
        0x00    /* bInterval */
        /* 25 */   
      };

    /* USB String Descriptors */
    const u8 Virtual_Com_Port_StringLangID[VIRTUAL_COM_PORT_SIZ_STRING_LANGID] =
      {
        VIRTUAL_COM_PORT_SIZ_STRING_LANGID,
        USB_STRING_DESCRIPTOR_TYPE,
        0x09,
        0x04 /* LangID = 0x0409: U.S. English */
      };

    const u8 Virtual_Com_Port_StringVendor[VIRTUAL_COM_PORT_SIZ_STRING_VENDOR] =
      {
        VIRTUAL_COM_PORT_SIZ_STRING_VENDOR,     /* Size of Vendor string */
        USB_STRING_DESCRIPTOR_TYPE,             /* bDescriptorType*/
        /* Manufacturer: "STMicroelectronics" */
        'S', 0, 'T', 0, 'M', 0, 'i', 0, 'c', 0, 'r', 0, 'o', 0, 'e', 0,
        'l', 0, 'e', 0, 'c', 0, 't', 0, 'r', 0, 'o', 0, 'n', 0, 'i', 0,
        'c', 0, 's', 0
      };

    const u8 Virtual_Com_Port_StringProduct[VIRTUAL_COM_PORT_SIZ_STRING_PRODUCT] =
      {
        VIRTUAL_COM_PORT_SIZ_STRING_PRODUCT,          /* bLength */
        USB_STRING_DESCRIPTOR_TYPE,        /* bDescriptorType */
        /* Product name: "Num send test" */
        'N', 0, 'u', 0, 'm', 0, ' ', 0, 's', 0, 'e', 0, 'n', 0, 'd', 0,
        ' ', 0, 't', 0, 'e', 0, 's', 0, 't', 0, ' ', 0
      };

    const u8 Virtual_Com_Port_StringSerial[VIRTUAL_COM_PORT_SIZ_STRING_SERIAL] =
      {
        VIRTUAL_COM_PORT_SIZ_STRING_SERIAL,           /* bLength */
        USB_STRING_DESCRIPTOR_TYPE,        /* bDescriptorType */
        'D', 0, 'e', 0, 'm', 0, 'o', 0, ' ', 0, '1', 0, '.', 0, '0', 0,
        '0', 0, '0', 0
      }
    有些字符没有修改还是原来DEMO的,大家将就着看看。
    还有就是Usb_prop.c 里面这个函数
    /*******************************************************************************
    * Function Name  : Virtual_Com_Port_Reset
    * Description    : Virtual_Com_Port Mouse reset routine
    * Input          : None.
    * Output         : None.
    * Return         : None.
    *******************************************************************************/
    void Virtual_Com_Port_Reset(void)  //USBIP复位过程,当宏单元收到RESET信号时调用,
    {                                  //用户程序在此过程中设置端点
      /* Set Virtual_Com_Port DEVICE as not configured */
      pInformation->Current_Configuration = 0;

      /* Set Virtual_Com_Port DEVICE with the default Interface*/
      pInformation->Current_Interface = 0;
      SetBTABLE(BTABLE_ADDRESS);

      /* Initialize Endpoint 0 */
      SetEPType(ENDP0, EP_CONTROL);
      SetEPTxStatus(ENDP0, EP_TX_STALL);
      SetEPRxAddr(ENDP0, ENDP0_RXADDR);
      SetEPTxAddr(ENDP0, ENDP0_TXADDR);
      Clear_Status_Out(ENDP0);
      SetEPRxCount(ENDP0, Device_Property.MaxPacketSize);
      SetEPRxValid(ENDP0);

      /* Initialize Endpoint 1 */
      SetEPType(ENDP1, EP_BULK);  //设置端点1传输模式批量传输
      SetEPTxAddr(ENDP1, ENDP1_TXADDR);  //缓冲区基地址(IN 发)
      SetEPTxCount(ENDP1, 64);  //配置Tx缓冲计数器
      SetEPTxStatus(ENDP1, EP_TX_VALID);  //设置端点发送有效
      SetEPRxStatus(ENDP1, EP_RX_DIS);  //设置端点接收关闭
       
      /* Initialize Endpoint 3 */
      SetEPType(ENDP3, EP_BULK);  //设置端点3传输模式批量传输
      SetEPRxAddr(ENDP3, ENDP3_RXADDR);  //缓冲区基地址(OUT 收)
      SetEPRxCount(ENDP3, 2); //配置Rx缓冲计数器
      SetEPRxStatus(ENDP3, EP_RX_VALID);  //设置端点接收有效
      SetEPTxStatus(ENDP3, EP_TX_DIS);  //端点关闭发送

      /* Set this device to response on default address */
      SetDeviceAddress(0);
    }要配置下。就是你开启的那些端点了。

    4  Windows XP下USB设备驱动的开发
      这部分是最麻烦的,至少对我来说是这样的,好像已经到了计算机专业范畴,而我对这些非常不熟悉。学习期间第一个方案用的是LABVIEW,它附带一个工具叫VISA,可以直接配置成USB驱动,然后再在LABVIEW里面直接调用,很方便。在研究LABVIEW的时候发现里面有很多DEMO,而且对中文的支持非常好,很多文档都是官方直接出中文文档。(好像半导体大额们对中国这块市场都越来越重视了,前几天看到AVR大部分的文档也都是直接官方翻译的中文文档。)学习了软件里面附带的入门教程,大概也能编一些简单的程序了,调试USB的时候发现里面有几个USB的demo,配合VISA生成的驱动居然直接接收到了下面传上来的数据,这对我们来说无异于是一次莫大的鼓励。后来导师推荐我试试另一种方法,就是用Driverstudio+VC来开发驱动和编写界面。为了学习一下USB的驱动开发,于是在第三个星期的时候开始windows下驱动的开发。老实说吃了很多苦头,到现在虽然功能基本实现了,但是对于这一块我还是只知道皮毛。DS里面的那些类和函数也没怎么搞透,驱动能开发出来主要还是借鉴了DS附带的example 里面的USB BULK 程序。
    下面大概讲下我遇到过的问题给后来人一点借鉴:

    (1)是安装顺序的问题,因为DriverStudio要嵌入到VC中,以后的代码要用DDK来编写所以三个软件要很好的兼容才可以。
    第一步:安装Microsoft Visual C++6.0;
    第二步:安装Microsoft Windows XP DDK;
    第三步:安装DriverStudio 3.2驱动程序开发工具包。
      VC6.0最好安装英文版的,可以减少不知名的错误。安装完成后DS3.2会嵌入到VC中,在上面多一个标题:
      DriverStudio选项卡下面第三项DDK Build setting要设置成C:\WINDDK\2600(如果DDK安装在C盘),然后要编译DriverStudio安装目录下DriverStudio\DriverWorks\source\VdwLibs.dsw,以得到vdw_wdm.lib这个库文件。编译的时候会出现错误,因为用VC打开vdwlibs.dsw工程文件后,有两个工程,要先将VdwLibs工程设为当前Active Project,然后在工具栏上单击右键选择“组建”,在弹出的编译工具栏中配置一下编译平台的设置:选择Win32 WDM Checked平台(因为我们用的XP),然后编译就应该可以了。

    (2)是利用向导生成驱动程序框架
      DS有个DriverWizard可以生成驱动程序的大体框架。
    第一步:选择开发环境VC6.0,命名。
    第二步:选择WDM Driver不用修改。
    第三步:选择WDM Function Driver
    第四步:选择USB并设置好PID 和 VID 要与固件里面的设置相同
    第五步:设置端点,以及缓冲区。也要和固件里面相对应。
      接下午几步可以根据自己来设置,也可以默认。完成后会生成一个工程目录,里面包含了两个工程,一个是驱动,是我们需要的。另一个是测试程序,好像没有用。当你编译驱动的时候,会提示有错误,这是因为DS里面的一个BUG,选择project-setting,左边两个工程选驱动那个,点右边LINK选项卡,删除Object/library module 项的ntstrsafe.lib。再编译就能通过了。
    (3)接下去就是对刚才生成的框架进行研究,添加一些代码以使驱动完整。
      首先来了解下生成的框架。
       DriverEntry()该例程是当系统检测到与驱动程序支持的设备时被调用的。
       AddDevice()  该例程为系统添加一个设备。
       Unload()          该例程为系统卸载设备。
      以上几个例程都存在于XXXXDriver.cpp是设备的基本操作可以直接使用生成的代码,不用修改。
      在另一个文件XXXXDevice.cpp中包含了具体应用函数,比如read和write,但是这个文件也存在这一个BUG,在开头部分有m_Pipe1_in.Initialize(m_Lower, 0x81, 64);        和m_Pipe2_out.Initialize(m_Lower, 3, 64);本次定义了两个端点,一个是叫m_Pipe1_in,0x81表示这个管道的属性是入(in),缓冲区是64.下面一个是m_Pipe2_out表示是出(out),缓冲区是64.向导生成的代码里面漏掉了“0x”这两个字符。
      关键部分代码的添加
      上位机应用程序,主要是通过两种方式来控制驱动,一个是DeviceIoControl()函数,另一个是ReadFile()函数和WriteFile()函数。本次使用的是后者。只要在Read(KIrp I),和Write(KIrp I)里面添加相应的代码就可以。这方面可以参考DS3.2附带的example里面的那个usbbulk例程。
      首先简述一下完成一次驱动调用所要做的具体工作。应用程序想对USB设备进行I/O操作,它需调用Windows API函数比如readfile(),I/O管理器将此请求构造成一个合适的I/O请求包(IRP)并把它传递给USB设备驱动程序。USB设备驱动程序接收到这个IRP后,根据IPR中包含的具体操作代码构造相应USB请求块(URB),并把它放到一个新的IRP中,然后传递给USB底层驱动程序(中间层或总线驱动程序)。USB底层驱动程序根据IRP中所含的URB执行相应的操作,并把操作的结果返回给USB设备驱动程序。USB设备驱动程序接收到此返回的IRP后,将操作结果通过IRP返还给I/O管理器,最后I/O管理器将此IRP操作结果传回给应用程序,至此应用程序对设备的一次I/O操作完成。当上位机调用的ReadFile()的时候,USB设备驱动程序要根据IPR中包含的具体操作代码构造相应USB请求块(URB),这个URB的生成就在这里实现,比如例程里面的
        PURB pUrb = m_Pipe1_in.BuildBulkTransfer(
                                                            Mem,                  // Where is data coming from?
                                                            dwTotalSize,  // How much data to read?
                                                            TRUE,         // direction (TRUE = IN)
                                                            NULL              // Link to next URB
                                                            );
      主要是通过这个函数来实现。函数实现了之后会有不同的返回值,然后打印出不同的信息。这些信息可以在DS调试工具Monitor中看到。

    5  驱动开发的过程大概就是这样了。下面是应用程序的开发。主要两步,先打开设备,然后读写数据。
    (1)打开设备
      Windows下面有很多针对驱动调用的API函数,要调用一个USB设备首先就要打开这个设备,其对应的API函数为CreateFile,在本次驱动中DS自动生成了一个OpenByInterface.c文件,在该文件里面对这个CreateFile函数进行了封装,其参数如下
    HANDLE OpenByInterface(
                    GUID* pClassGuid,        // points to the GUID that identifies the interface class
                    DWORD instance,                // specifies which instance of the enumerated devices to open
                    PDWORD pError                // address of variable to receive error status
                    )
    所以在主程序中只要调用OpenByInterface函数就可以了。本次中具体实现的代码如下:
            if(g_hUsbDevice==INVALID_HANDLE_VALUE)
            {
                    g_hUsbDevice=OpenByInterface(
                            &g_UsbGuid,        // points to the GUID that identifies the interface class
                            0,                // specifies which instance of the enumerated devices to open
                            &Error                // address of variable to receive error status
                            );
                    if(g_hUsbDevice==INVALID_HANDLE_VALUE)
                    {
                            MessageBox("打开设备失败!",NULL,MB_OK | MB_ICONHAND);
                    }
                    else
                    {
                            MessageBox("打开设备成功!",NULL,MB_OK | MB_ICONASTERISK);                 
                    }
            }
    其中GUID* pClassGuid是对应的设备的GUID,具体定义如下:
    GUID g_UsbGuid=GUID_DEVINTERFACE_USB;//打开设备的GUID
    其中GUID_DEVINTERFACE_USB是在DS生成的Intrface.h文件中定义的,
    #define GUID_DEVINTERFACE_USB \
    { 0x6C8CFFA6, 0xCAB8, 0x45B1, { 0xAA, 0xEE, 0x1E, 0xF4, 0xDF, 0x79, 0xF8, 0xDF } }
    这个ID保证了每个USB驱动的唯一性,调用紊乱的情况的出现。OpenByInterface这个函数有一个返回值,通过的改变可以确认设备是否打开成功,然后通过MessageBox函数跳出不同的反馈信息。
    (2)读写数据
      Windows中读取数据的API函数有两种,一种是DeviceIoControl,一种是ReadFile、WriteFile函数。前者一个函数可以读也可以写,后者把读写分开来,这次使用的是后者。
      ReadFile的具体实现如下:
    ReadFile(
                                    g_hUsbDevice,        //我们的设备HANDLE hFile
                                    DataBuffer,//输入缓冲,无lpBuffer
                    64,                        //输出字节数nNumberOfBytesToRead,
                    &BytesReturned,        //实际读取到的字节数lpNumberOfBytesRead,
                    NULL
                        )
      g_hUsbDevice是对应我们的设备,DataBuffer是我们定义的数组,读取到的数据就存在这个数组中,64是一次读取的字节数,BytesReturned是实际读取到的字节数,最后一个可以默认为NULL。如果成功读取到了数据,数组DataBuffer中的数据就会更新,然后可以做任意处理。
      写数据基本和读取数据类似。

      至此基本完成了驱动的开发。主要是论述下我学习的整个过程,因为在学习的过程中,最大的苦恼是有时不知道应该朝哪里努力。套用圈圈的一句话:真希望能来个大仙来指指路。涉及到的内容相对本科毕设还是比较多的。很多地方都没吃透。
      第一次发帖,先在word上编辑好的,格式可能会有错误。  帖子里有些内容是我从论文里直接复制过来的。东西是去年做的,没有及时做总结,很多地方都忘掉了。可能会有很多错误,大家指正。
      留下我的联系方式:E-MAIL:fmj118@gmail.com   QQ :110053142 大家有啥新发现不要忘了我啊。最近在想开始学习UCOS如果有做过这块的同学,现在正在搞USB。能交换学习就更好了。
      刚刚发现量这个帖子
    http://www.ouravr.com/bbs/bbs_content.jsp?bbs_sn=1843081&bbs_page_no=1&search_mode=1&search_text=usb&bbs_id=3020
    也是包括了固件,驱动,上位机写的比我详细很多,一起学习下。


    * - 本贴最后修改时间:2009-3-11 10:48:13 修改者:fmj2008

     

    系统分类: ARM   |    用户分类:    |    来源: 转贴

    该用户于2009/3/14 8:44:53编辑过该文章

    评论(1) | 阅读(819)
    发表于:2009/3/12 20:10:23
    标签:无标签

    3

    【转帖】模拟电路的四重境界

    无意中看到这个文章,虽然自己也搞了4 年模电了,但后看完之后发现自己原来根本就没有入门阿!现发上来和大家共享!·············复旦攻读微电子专业模拟芯片设计方向研究生开始到现在五年工作经验,已经整整八年了,其间聆听过很多国内外专家的指点。最近,应朋友之邀,写一点心得体会和大家共享。我记得本科刚毕业时,由于本人打算研究传感器的,后来阴差阳错进了复旦逸夫楼专用集成电路与系统国家重点实验室做研究生。现在想来这个实验室名字大有深意,只是当时惘然。电路和系统,看上去是两个概念, 两个层次。我同学有读电子学与信息系统方向研究生的,那时候知道他们是“系统”的, 而我们呢,是做模拟“电路”设计的,自然要偏向电路。而模拟芯片设计初学者对奇思淫巧的电路总是很崇拜,尤其是这个领域的最权威的杂志JSSC (IEEE Journal of solid state circuits), 以前非常喜欢看, 当时立志看完近二十年的文章,打通奇经八脉,总是憧憬啥时候咱也灌水一篇, 那时候国内在此杂志发的文章凤毛麟角, 就是在国外读博士,能够在上面发一篇也属优秀了。读研时,我导师是郑增钰教授,李联老师当时已经退休,逸夫楼邀请李老师每个礼拜过来指导。郑老师治学严谨,女中豪杰。李老师在模拟电路方面属于国内先驱人物,现在在很多公司被聘请为专家或顾问。李老师在87 年写的一本(运算放大器设计);即使现在看来也是经典之作。李老师和郑老师是同班同学,所以很要好,我自然相对于我同学能够幸运地得到李老师的指点。李老师和郑老师给我的培养方案是:先从运算放大器学起。所以我记得我刚开始从小电流源开始设计。那时候感觉设计就是靠仿真调整参数。但是我却永远记住了李老师语重心长的话:运放是基础,运放设计弄好了,其他的也就容易了。当时不大理解,我同学的课题都是AD/DA,锁相环等“高端”的东东,而李老师和郑老师却要我做“原始”的模块,我仅有的在(固体电子学) (国内的垃圾杂志)发过的一篇论文就是轨到轨(rail-to-rail)放大器。做的过程中很郁闷,非常羡慕我同学的项目,但是感觉李老师和郑老师讲的总有他们道理,所以我就专门看JSSC 运放方面的文章,基本上近20 多年的全看了。当时以为很懂这个了,后来工作后才发现其实还没懂。所谓懂,是要真正融会贯通,否则塞在脑袋里的知识再多,也是死的。但是运算放大器是模拟电路的基石,只有根基扎实方能枝繁叶茂,两位老师的良苦用心工作以后才明白。总的来说,在复旦,我感触最深的就是郑老师的严谨治学之风和李老师的这句话。硕士毕业,去找工作,当时有几个offer。我师兄孙立平, 李老师的关门弟子,推荐我去新涛科技,他说里面有个常仲元,鲁汶天主教大学博士,很厉害。我听从师兄建议就去了。新涛当时已经被IDT 以8500 万美金收购了,成为国内第一家成功的芯片公司。面试我的是公司创始人之一的总经理Howard. C. Yang(杨崇和)。Howard 是Oregon State University 的博士,锁相环专家。面试时他当时要我画了一个两级放大器带Miller 补偿的, 我很熟练。他说你面有个零点,我很奇怪,从没听过,云里雾里,后来才知道这个是Howard 在国际上首先提出来的, 等效模型中有个电阻,他自己命名为杨氏电阻。当时出于礼貌,不断点头。不过他们还是很满意,反正就这样进去了。我呢,面试的惟一的遗憾是没见到常仲元, 大概他出差了。进入新涛后,下了决心准备术业有专攻。因为本科和研究生时喜欢物理,数学和哲学,花了些精力在这些上面。工作后就得真刀真枪的干了。每天上班仿真之余和下班后,就狂看英文原版书。第一本就是现在流行的Razavi 的那本书。读了三遍。感觉大有收获。那时候在新涛,初生牛犊不怕虎,应该来说,我还是做得很出色的,因此得到常总的赏识,被他评价为公司内最有potential的人。偶尔常总会过来指点一把,别人很羡慕。其实我就记住了常总有次聊天时给我讲的心得, 他大意是说做模拟电路设计有三个境界:第一是会手算,意思是说pensile-to-paper, 电路其实应该手算的,仿真只是证明手算的结果。第二是,算后要思考,把电路变成一个直观的东西。第三就是创造电路。我大体上按照这三部曲进行的。Razavi 的那本书后面的习题我仔细算了。公司的项目中,我也力图首先以手算为主, 放大器的那些参数,都是首先计算再和仿真结果对比。久而久之,我手计算的能力大大提高,一些小信号分析计算,感觉非常顺手。这里讲一个小插曲,有一次在一个项目中,一个保护回路AC 仿真总不稳定, 调来调去,总不行,这儿加电容,那儿加电阻,试了几下都不行,就找常总了。因为这个回路很大,所以感觉是瞎子摸象。常总一过来三下五除二就摆平了, 他仔细看了,然后就导出一个公式,找出了主极点和带宽表达式。通过这件事,我对常总佩服得五体投地, 同时也知道直观的威力。所以后来看书时,都会仔细推导书中的公式,然后再直观思考信号流, 不直观不罢手。一年多下来, 对放大器终于能够透彻理解了,感觉学通了, 通之后发现一通百通。最后总结:放大器有两个难点,一个是频率响应,一个是反馈。其实所谓电路直观,就是用从反馈的角度来思考电路。每次分析了一些书上或者JSSC 上的“怪异”电路后,都会感叹:反馈呀,反馈!然后把分析的心得写在paper 上面。学通一个领域后再学其他相关领域会有某种“加速”作用。常总的方式是每次做一个新项目时,让下面人先研究研究。我在离开新涛前,做了一个锁相环。我以前没做过,然后就把我同学的硕士论文,以及书和很多paper 弄来研究,研究了一个半月,常总过来问我:锁相环的3dB 带宽弄懂了吧? 我笑答:早就弄懂了。我强大的运放的频率响应知识用在锁相环上,小菜了。我这时已经去研究高深的相位噪声和jitter 了。之后不久,一份30 多页的英文研究报告发出来,常总大加赞赏!。后来在COMMIT时,有个项目是修改一个RF Transceiver 芯片, 使之从WCDMA 到TD-SCDMA。里面有个基带模拟滤波器。我以前从没接触过滤波器,就花了两个月时间,看了三本英文原版书,第一本有900 多页,和N 多paper, 一下子对整个滤波器领域,开关电容的,GmC 的,Active RC 的都懂了。提出修改方案时, 由于我运放根基扎实,看文章时对于滤波器信号流很容易懂,所以很短时间就能一个人提出芯片电路原理分析和修改方案。最后报告写出来(也是我的又一个得意之作),送给TI. TI 那边对这边一下子肃然起敬,Conference call 时, 他们首先说这份报告是“Great job!”,我英文没听懂,Julian 对我夸大拇指,说“他们对你评价很高呢”。后来去Dallas, TI 那边对我们很尊敬, 我做报告时,很多人来听。总之,现在知道,凡事情,基础很重要,基础扎实学其他的很容易切入, 并且越学越快。我是02 年11 月去的COMMIT,当时面试我的也是我现在公司老板Julian。Julian 问我:你觉得SOC (system on chip)设计的环节在哪儿? 我说:应该是模拟电路吧,这个比较难一些。Julian 说错了,是系统。我当时很不以为然, 觉得模拟电路工程师应该花精力在分析和设计电路上。Julian 后来自己run 了现在这公司On-Bright,把我也带来, 同时也从TI 拉了两个,有一个是方博士。我呢,给Julian 推荐了朱博士。这一两年,我和朱博士对方博士佩服得五体投地。方博士是TI 华人里面的顶级高手,做产品能力超强。On-Bright 现在做电源芯片,我和朱博士做了近两年,知道了系统的重要性。芯片设计最终一定要走向系统,这个是芯片设计的第四重境界。电路如同砖瓦,系统如同大厦。芯片设计工程师一定要从系统角度考虑问题,否则就是只见树木,不见森林。电源芯片中,放大器,比较器都是最最普通的, 其难点在于对系统的透彻理解。在On-Bright,我真正见识了做产品,从定义到设计,再到debug, 芯片测试和系统测试,最后到RTP (release to production)。Julian 把TI 的先进产品开发流程和项目管理方式引入On-Bright,我和朱博士算是大开眼界,也知道了做产品的艰辛。

    系统分类: 模拟技术   |    用户分类:    |    来源: 转贴

    该用户于2009/3/12 20:10:35编辑过该文章

    评论(1) | 阅读(297)
    发表于:2009/3/12 19:20:09
    标签:485,AVR,PROTESU,仿真  

    2

    USART接485发送+PROTESU仿真

    仿真截图

    点击开大图

    //ICC-AVR application builder : 2007-11-30 20:29:49
    //串口+485发送程序
    // Target : M16
    // Crystal: 8.0000Mhz
    //编制:孙可

    #include <iom16v.h>
    #include <macros.h>
    void x_print(unsigned char c) //发送采用查询方式
    {
    while( !(UCSRA & (1<<UDRE)) );
    UDR=c;
    }




    void port_init(void)
    {
    PORTA = 0x00;
    DDRA = 0x00;
    PORTB = 0x00;
    DDRB = 0x00;
    PORTC = 0x00; //m103 output only
    DDRC = 0x00;
    PORTD = 0x40;
    DDRD = 0x40;
    }

    //UART0 initialize
    // desired baud rate: 9600
    // actual: baud rate:9615 (0.2%)
    void uart0_init(void)
    {
    UCSRB = 0x00; //disable while setting baud rate
    UCSRA = 0x00;
    UCSRC = BIT(URSEL) | 0x0E;
    UBRRL = 0x33; //set baud rate lo
    UBRRH = 0x00; //set baud rate hi
    UCSRB = 0x98;
    }

    #pragma interrupt_handler uart0_rx_isr:iv_USART0_RXC
    void uart0_rx_isr(void)
    {
    //uart has received a character in UDR
    }

    //call this routine to initialize all peripherals
    void init_devices(void)
    {
    //stop errant interrupts until set up
    CLI(); //disable all interrupts
    port_init();
    uart0_init();

    MCUCR = 0x00;
    GICR = 0x00;
    TIMSK = 0x00; //timer interrupt sources
    SEI(); //re-enable interrupts
    //all peripherals are now initialized
    }
    void main(void)
    {
    init_devices();
    while(1)
    {
    unsigned int i="0x55";
    unsigned int j="0xaa";
    x_print(i);
    x_print(j);
    }
    }

    rar仿真+程序包

    系统分类: 单片机   |    用户分类:    |    来源: 原创

    该用户于2009/3/12 19:20:20编辑过该文章

    评论(2) | 阅读(600)
    发表于:2009/3/2 10:43:10
    标签:博客大赛  TI  

    1

    又参加电源网的博客大赛了

    用户名:小可歌

    欢迎大家帮我顶,给我投票,谢谢!

    投票地址:http://www.dianyuan.com/wangping/ti/blog_index.php

    顶贴地址:http://sunke9.blog.dianyuan.com/ti.php?author_id=198046

    08年到09年参加了3次EDN组织的博客大赛,得了2个2等奖、1个3等奖,快成博客专业户了,呵呵。

    系统分类: 生活点滴   |    用户分类:    |    来源: 原创

    该用户于2009/3/6 10:19:43编辑过该文章

    评论(0) | 阅读(406)
    发表于:2009/1/6 17:01:14
    标签:TLC2543  TLV5618  P521  模拟  

    24

    【原创】用TLC2543和TLV5618加P521打造隔离的单片机模拟输入输出系统

     一看标题可能有的朋友就会问了,你怎么又用P521啊?您先别着急,嘿嘿,我是又用P521了,因为P521价格便宜量又足我当然用它了。P521就是光耦里面的“大宝SOD”!

    简单介绍一下TLC2543

    TLC2543是TI公司的12位串行模数转换器,使用开关电容逐次逼近技术完成A/D转换过程。由于是串行输入结构,能够节省单片机I/O资源;且价格适中,分辨率较高,因此在仪器仪表中有较为广泛的应用

    TLC2543的特点

    (1)12位分辩率A/D转换器;
    (2)在工作温度范围内10μs转换时间;
    (3)11个模拟输入通道;
    (4)3路内置自测试方式;
    (5)采样率为66kbps;

    (6)线性误差±1LSBmax;
    (7)有转换结束输出EOC;
    (8)具有单、双极性输出;
    (9)可编程的MSB或LSB前导;
    (10)可编程输出数据长度。

    再说说TLV5618

    TLC5618 是美国TexasInstruments 公司生产的带有缓冲基准输入的可编程双路12 位数/模转换器。DAC 输出电压范围为基准电压的两倍,且其输出是单调变化的。该器件使用简单,用5V 单电源工作,并包含上电复位功能以确保可重复启动。通过CMOS兼容的3线串行总线可对TLC5618 实现数字控制。器件接收用于编程的16 位字产生模拟输出。数字输入端的特点是带有斯密特触发器,因而具有高的噪声抑制能力。

    TLV5618特点

    (1)可编程至0.5LSB 的建立时间;

    (2)两个12 位的CMOS 电压输出DAC;

    (3)单电源工作;

    (4)3 线串行接口;

    (5)高阻抗基准输入;

    (6)电压输出范围为基准电压的两倍;

    (7)软件断电方式;

    (8)内部上电复位;

    (9)低功耗,慢速方式为3mW,快速方式为8mW;

    (10)1.21MHz 输入数据更新速率;

    (11)在工作温度范围内单调变化。点击看大图

    看图,这是我在电源模块中的应用,电源模块的内部干扰严重,为了单片机的稳定工作特设计了这样的模拟输入输出系统。把这两个芯片并在一起接到单片机上一共占用5个IO口:一个时钟输出CLK、一个数据输入IN、一个数据输出OUT、两个片选CS。用P521做隔离,构成12位的输入输出系统,级别够高吧?11个模拟输入,2个模拟输出干啥都够用了。怎么样?值得投我一票吧?我这篇文章是博客大赛参赛文章,麻烦看过的朋友到左上角顶我一下,谢谢!

    系统分类: 模拟技术   |    用户分类:    |    来源: 原创

    该用户于2009/1/6 18:39:51编辑过该文章

    评论(14) | 阅读(2369)
    发表于:2008/12/15 8:28:56
    标签:232  485  65LBC184  

    63

    做串口的232转485通讯遇到的问题[原创]

    说的还是前一段时间给老板的朋友做控制器的事,在这个小项目上我可真是长见识了。在这个项目里用到了一个霍尼韦尔的传感器,传感器是通过232口和上位机通讯的,通讯波特率2400,数据格式1位起始位、1位停止位、8位数据位、没有奇偶校验、每帧数据有一个求和校验。有3中命令:50  03  AD;50  00  B0;50 01 AF。这里咱们不研究通讯数据就不细说了,总之看起来很简单。刚拿到传感器的时候我得先检验一下是不是好使,接上电源,接通232到我电脑的串口1,然后用串口调试软件发命令,传感器很快有了相应,这证明传感器是好的,可以放心的做我的工作了。

    做程序之前我还要知道传感器响应的速度,这有关于我单片机处理能力,所以找来串口调试软件Commix这个软件可以显示发送到接收的时间。

     点击开大图

    测得结果还不算快,两个命令是10多毫秒的,一个命令是1秒多的,我的ATMEGA8完全可以应付得过来。这里要说一下,这个传感器是232口的,它工作的地方距离我的控制器100多米,由于232的传输有效距离是15米,我们需要把232转成485传到我的控制器上,485的有效传输距离可达1000米。

    测过通讯我就动手做程序了,没到一个星期就做好了,可问题接着就来了,当我把传感器接上232转485转换器连到我的控制器的485口上时无论如何也通不上。用另一个232转485接到电脑上监视通讯数据时发现控制器发出的命令成了乱码,我的控制器通过一个232转485接到电脑上通讯正常,原来试传感器接电脑也正常,再试试传感器接232转485再接232转485接到电脑上,通讯失败。于是怀疑是传感器的232口带不动485转换器,让老板买了一个232和485端都带驱动带隔离的转接器回来一试还是不行。从网上找来一个232转485的电路,自己动手用MAX232和65LBC184搭了一个转换电路,仍然不行。点击开大图

    本来是很规则的波形,变成了杂乱无章的波形。

    点击开大图

    现在的矛盾就都集中在控制485方向的三极管上了,为什么它不能正确控制方向呢?把传感器接到电脑上用示波器同监视232口的2和3脚才发现,原来当电脑向传感器发命令的同时,传感器同时向电脑返回接收到的命令,这两个波形是同步的,它就是导致232转485转换器搞不清方向的原因。232口是全双工的,发送的同时允许接收,可485不行485在同一时间内只能发或者收。我的控制器上的485电路是死的了,不能再改了,传感器的232电路也改不了,

    点击开大图

    485接口电路

    只能从转换器身上想办法了。用个CPU控制232和485在中间做翻译工作,写了一小段程序才解决了问题。看起来不是所有的232都能随便转成485啊,还要看信号的规则。这个小项目可让我长知识了,东西不大麻烦不少。我这篇文章是博客大赛参赛文章,麻烦看过的朋友到左上角顶我一下,谢谢!

    系统分类: 模拟技术   |    用户分类:    |    来源: 原创

    该用户于2009/1/3 20:21:10编辑过该文章

    评论(17) | 阅读(3497)
    234567Next >Total , Page /