这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » (NRF24L01驱动成功)hanshuyujifen2的 ARM DIY进程贴

共191条 17/20 |‹ 15 16 17 18 19 20 跳转至
高工
2012-05-31 11:23:16     打赏
161楼
串口DMA方式发送数据

需要用到DMA方式处理一些数据。可我对DMA不太了解,上午没事就拿串口开刀。参考原子的代码,做了串口DMA方式发送数据的实验。
以下注释是实验的产物。
1、DMA初始化
void DMA_Configuration(void)
{
    DMA_DeInit(DMA1_Channel4);   //将DMA的通道1寄存器重设为缺省值
    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR;  //DMA外设基地址。DMA将数据写入这个寄存器。写入后直接发送
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SendBuff;  //DMA内存基地址,在内存中。相当于数据源。
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;  //外设作为数据传输的目的地。传输方式从内存到外设。USART为外设
    DMA_InitStructure.DMA_BufferSize = sizeof(SendBuff);  //DMA通道的DMA缓存的大小。一次传输的数据量,不大于65535
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  //USART1->DR地址是固定的
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  //内存地址寄存器递增。读一个数据后,自动移动到下一个数据
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;  //外设数据宽度,即DR的位数
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //数据宽度为8位。元数据宽度
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//DMA_Mode_Normal;  //工作在循环模式,手动停止
    DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //DMA通道,中优先级
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;   //不是内存到内存传输。
    DMA_Init(DMA1_Channel4, &DMA_InitStructure);  //根据DMA_InitStruct中指定的参数初始化DMA的通道USART1_Tx_DMA_Channel所标识的寄存器
}


2、主函数中调用
    USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);  //使能UART DMA传输
    /* Enable USART1 TX DMA1 Channel */
    DMA_Cmd(DMA1_Channel4, DISABLE );  //关闭USART1 TX DMA1 所指示的DMA通道     
     //DMA_Configuration();
    DMA_InitStructure.DMA_BufferSize = sizeof(SendBuff);  //DMA通道的DMA缓存的大小
    DMA_Init(DMA1_Channel4, &DMA_InitStructure);  //根据DMA_InitStruct中指定的参数初始化DMA的通道USART1_Tx_DMA_Channel所标识的寄存器
    DMA_Cmd(DMA1_Channel4, ENABLE);  //使能USART1 TX DMA1 所指示的通道
    //扫描按键停止DMA
    while(1)
    {
        t=KEY_Scan();
        if(t==1)//KEY0按下   
        {
            USART_DMACmd(USART1, USART_DMAReq_Tx, DISABLE);   
            DMA_Cmd(DMA1_Channel4, DISABLE );
        }
    }

高工
2012-05-31 21:22:47     打赏
162楼
定时器触发DMA方式的DAC

使用定时器触发DAC转换,弄了几天终于搞定。
今天这个实验的整个工作过程是这样的:

1、先定义一个数据源,作为DMA时的数据源
uint8_t Escalator8bit[5000] = {0x0,0x11,0x22,0x33,0x44,0x55, 0x66,0x77,0x88,0x99,0xaa,0xbb,0xCC,0xdd,0xee, 0xFF};

2、配置GPIO  DAC1 DAC2分别对应PA4和PA5
void DAC_GPIOConfig(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_4 | GPIO_Pin_5;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;       //必须是模拟输出模式
    GPIO_Init(GPIOA, &GPIO_InitStructure);
}

3、使能时钟。
GPIOA和DAC不用说了,那是必须的。由于使用了TIM6触发DAC1转换,需要使能TIM6时钟。
使用了DMA2的3号通道,需要使能DMA2时钟。
DAC使用那个通道进行DMA,参看STM32参考手册中文版第148和149页关于DMA请求映像的描述
void DAC_RCCConfig(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);     
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);     //别开错时钟了
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);

}

4、TIM6设置
    TIM_PrescalerConfig(TIM6, 0xF, TIM_PSCReloadMode_Update);   //TIM6预分频
    TIM_SetAutoreload(TIM6, 0xFF);                                   //自动装载的值。
    TIM_SelectOutputTrigger(TIM6, TIM_TRGOSource_Update);        //产生什么样的触发信号。选择产生更新信号

5、DAC的初始化
    //DAC初始化
    DAC_InitStructure.DAC_Trigger = DAC_Trigger_T6_TRGO;    //选择触发源
    DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
    //使能OutputBuffer可提高带负载能力。接耳机,实测:关闭OutputBuffer时声音很小几乎听不见。使能后声音还可以
    DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
    DAC_Init(DAC_Channel_1, &DAC_InitStructure);

6、DMA配置
    DMA_DeInit(DMA2_Channel3);   //DMA2的3号通道。必须是这个通道
    DMA_InitStructure.DMA_PeripheralBaseAddr = DAC_DHR8R1_Address;   //外设地址,即DAC通道 1的 8位右对齐数据保持寄存器(DAC_DHR8R1)地址
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&Escalator8bit;  //源数据地址
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;  //外设是数据目标
    DMA_InitStructure.DMA_BufferSize = sizeof(Escalator8bit);          //Escalator8bit的大小
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;   //禁止外设地址自动增长
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;     //源数据地址自动增长
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;  //外设数据宽度
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;       //存储器数据宽度
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;        //循环模式
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
   
    DMA_Init(DMA2_Channel3, &DMA_InitStructure);

7、之后就可以使能DMA功能和定时器触发了
    DAC_Cmd(DAC_Channel_1, ENABLE);   //使能DAC
    DAC_DMACmd(DAC_Channel_1, ENABLE); //使能DAC的DMA功能

    TIM_Cmd(TIM6, ENABLE);   //使能TIM6  按照手册要求,TIM6必须在DAC使能之后再使能

接上耳机,会听见一个很单调的声音。大约1K不到的频率。
谁玩过MIG 29或者LOCK ON这个游戏的话,会很熟悉这个声音。
8、测试代码
    My_DAC2_Init();
    while(1)
    {
        //printf("当前DAC输出值为:%d mv\r\n",(3300*DAC_GetDataOutputValue(DAC_Channel_1))/4095);
        if(TIM_GetFlagStatus (TIM6,TIM_FLAG_Update) == SUCCESS )
        {
            TIM_ClearFlag(TIM6,TIM_FLAG_Update);
            printf("当前DAC输出值为:%d mv\r\n",(3300*DAC_GetDataOutputValue(DAC_Channel_1))/4095);       
        }
    }
上图:(稍后补上)
我的耳机:

数据图:

高工
2012-06-01 21:22:10     打赏
163楼
LCD和SRAM同时工作测试代码

就这么一个实验,同时工作不冲突。
工程包含了LCD的驱动和SRAM驱动。Ctrl+F5直接运行即可。
本来想加入串口程序,后来有问题就删掉了。有兴趣的童鞋可以加进去吧用电脑件事SRAM的数据读写
工程使用12M晶振,使用8M晶振的童鞋需要改一下。更改方式请参看jobs的进程贴
代码包如下:


http://share.eepw.com.cn/share/download/id/75363

高工
2012-06-04 20:22:28     打赏
164楼
一晚上,试验dac输出wav。没搞定,郁闷。没有示波器,看输出完全靠耳朵,真麻烦啊。暂停mp3解码,等时机到了,工具全了再来搞。

高工
2012-06-05 21:02:53     打赏
165楼
开始玩CAN

晚上弄了下CAN  准备实现LoopBack模式的数据收发。就是自己收自己发送的数据。
LoopBack是CAN控制器的一种工作模式。板子只有一个CAN控制器,而且电阻也焊错了(原理图错误)。现在只能使用这种模式了。

在STM32参考手册里边的地428页这么讲的:
通过对CAN_BTR寄存器的LBKM位置’1’,来选择环回模式。在环回模式下,bxCAN把发送的报
文当作接收的报文并保存(如果可以通过接收过滤)在接收邮箱里。
环回模式可用于自测试。为了避免外部的影响,在环回模式下CAN内核忽略确认错误(在数据/远
程帧的确认位时刻,不检测是否有显性位)。在环回模式下,bxCAN在内部把Tx输出回馈到Rx输
入上,而完全忽略CANRX引脚的实际状态。发送的报文可以在CANTX引脚上检测到。

这只是一种只检测模式。
这种模式工作示意图如下:


如果有示波器,还可以看见CAN发送引脚的波形输出

今天只是学习下,没代码

高工
2012-06-07 21:18:47     打赏
166楼
连着上了几天班,早出晚归的一直没时间弄板子。
今天参考野火程序,弄了下CAN。还不错  Loopback模式正常收发数据。
配置CAN为中断接收模式

参考了野火的程序实现。
这里基本就是我对野火程序的理解,和拷贝
1、设置NVIC 使能CAN中断接收
static void CAN_NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;

  /* Enable CAN1 RX0 interrupt IRQ channel */
  NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;     //中断通道
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;     // 主优先级为0
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;            // 次优先级为0
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}

2、引脚GPIO设置
板子上的CAN引脚被从定义到了PB8和PB9.
需要使用AFIO的Renap功能
static void CAN_GPIO_Config(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
     
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOB, ENABLE);                                                                         

  /* CAN1 Periph clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);

  /* Configure CAN pin: RX */                                                   // PB8
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;                 // 上拉输入
  GPIO_Init(GPIOB, &GPIO_InitStructure);
 
  /* Configure CAN pin: TX */                                                   // PB9
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                 // 复用推挽输出
  GPIO_Init(GPIOB, &GPIO_InitStructure);
 
    //将CAN1引脚重定义到PB8  PB9  使用引脚服用功能
  GPIO_PinRemapConfig(GPIO_Remap1_CAN1, ENABLE);
}

3、将CAN配置为LoopBack模式
配置完成后发送一帧数据,并接收。以检查是否配置成功,此处的接收使用了查询方式
TestStatus CAN_Polling(void)
{
  CAN_InitTypeDef        CAN_InitStructure;
  CAN_FilterInitTypeDef  CAN_FilterInitStructure;
  CanTxMsg TxMessage;
  CanRxMsg RxMessage;
  uint32_t i = 0;
  uint8_t TransmitMailbox = 0;

  /* CAN register init */
  CAN_DeInit(CAN1);
  CAN_StructInit(&CAN_InitStructure);

  /* CAN cell init */
  CAN_InitStructure.CAN_TTCM=DISABLE;                         // 时间触发通信禁止
  CAN_InitStructure.CAN_ABOM=DISABLE;                         // 离线退出是在中断置位清0后退出
  CAN_InitStructure.CAN_AWUM=DISABLE;                         // 自动唤醒模式:清零sleep
  CAN_InitStructure.CAN_NART=DISABLE;                         // 自动重新传送豹纹,知道发送成功
  CAN_InitStructure.CAN_RFLM=DISABLE;                         // FIFO没有锁定,新报文覆盖旧报文 
  CAN_InitStructure.CAN_TXFP=DISABLE;                         // 发送报文优先级确定:标志符
  CAN_InitStructure.CAN_Mode=CAN_Mode_LoopBack;     // 回环模式
  CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;                 // 1tq、BS1、BS2的值跟波特率有关
  CAN_InitStructure.CAN_BS1=CAN_BS1_8tq;
  CAN_InitStructure.CAN_BS2=CAN_BS2_7tq;
  CAN_InitStructure.CAN_Prescaler=5;             // 分频系数为5
  CAN_Init(CAN1, &CAN_InitStructure);            // 初始化CAN1

  /* CAN 过滤器初始化 */
  CAN_FilterInitStructure.CAN_FilterNumber=0;
  CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;       //标识符过滤
  //使用32位过滤器,接收报文标识符的每一位都必须跟过滤器标识符相同
  CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;  
  CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;                   //设置标识符
  CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
  CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;
  CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
  CAN_FilterInitStructure.CAN_FilterFIFOAssignment=0;               //接收FIFO
  CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;                //使能过滤器
  CAN_FilterInit(&CAN_FilterInitStructure);

  /* transmit */
  TxMessage.StdId=0x11;                // 设定标准标识符(11位,扩展的为29位)
  TxMessage.RTR=CAN_RTR_DATA;    // 传输消息的帧类型为数据帧(还有远程帧)
  TxMessage.IDE=CAN_ID_STD;        // 消息标志符实验标准标识符
  TxMessage.DLC=2;                      // 发送两帧,一帧8位
  TxMessage.Data[0]=0xCA;            // 第一帧数据
  TxMessage.Data[1]=0xFE;            // 第二帧数据

  TransmitMailbox=CAN_Transmit(CAN1, &TxMessage);    //处理好数据后,将数据贞挂号等待发送。
  i = 0;
    // 用于检查消息传输是否正常
  while((CAN_TransmitStatus(CAN1, TransmitMailbox) != CANTXOK) && (i != 0xFF))
  {
    i++;
  }

  i = 0;
    // 检查返回的挂号的信息数目
  while((CAN_MessagePending(CAN1, CAN_FIFO0) < 1) && (i != 0xFF))
  {
    i++;
  }

  /* receive */
  RxMessage.StdId=0x00;
  RxMessage.IDE=CAN_ID_STD;
  RxMessage.DLC=0;
  RxMessage.Data[0]=0x00;
  RxMessage.Data[1]=0x00;
  CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);


  if (RxMessage.StdId!=0x11)
  {
    return FAILED; 
  }

  if (RxMessage.IDE!=CAN_ID_STD)
  {
    return FAILED;
  }

  if (RxMessage.DLC!=2)
  {
    return FAILED; 
  }

    /* 判断发送的信息和接收的信息是否相等 */
  if ((RxMessage.Data[0]<<8|RxMessage.Data[1])!=0xCAFE)
  {
    return FAILED;
  }

    //printf("receive data:0X%X,0X%X",RxMessage.Data[0], RxMessage.Data[1]); 

  return PASSED; /* Test Passed */
}

4、配置CAN的中断接收
TestStatus CAN_Interrupt(void)
{
  CAN_InitTypeDef        CAN_InitStructure;
  CAN_FilterInitTypeDef  CAN_FilterInitStructure;
  CanTxMsg TxMessage;
  uint32_t i = 0;

  /* CAN register init */
  CAN_DeInit(CAN1);
  CAN_StructInit(&CAN_InitStructure);

  /* CAN cell init */
  CAN_InitStructure.CAN_TTCM=DISABLE;           // 时间触发通信禁止
  CAN_InitStructure.CAN_ABOM=DISABLE;              // 离线退出是在中断置位清0后退出
  CAN_InitStructure.CAN_AWUM=DISABLE;              // 自动唤醒模式:清零sleep
  CAN_InitStructure.CAN_NART=DISABLE;              // 自动重新传送豹纹,知道发送成功
  CAN_InitStructure.CAN_RFLM=DISABLE;              // FIFO没有锁定,新报文覆盖旧报文
  CAN_InitStructure.CAN_TXFP=DISABLE;           // 发送报文优先级确定:标志符
  CAN_InitStructure.CAN_Mode=CAN_Mode_LoopBack; // 回环模式
  CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;        // 1tq、BS1、BS2的值跟波特率有关
  CAN_InitStructure.CAN_BS1=CAN_BS1_8tq;
  CAN_InitStructure.CAN_BS2=CAN_BS2_7tq;
  CAN_InitStructure.CAN_Prescaler=1;                      // 分频系数为1
  CAN_Init(CAN1, &CAN_InitStructure);                        // 初始化CAN1

  /* CAN filter init */
  CAN_FilterInitStructure.CAN_FilterNumber=1;
  CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
  CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;
  CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;
  CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
  CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;
  CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
  CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0;
  CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
  CAN_FilterInit(&CAN_FilterInitStructure);

  /* CAN FIFO0 message pending interrupt enable */
  CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE); //中断使能

  /* transmit 1 message */
  TxMessage.StdId=0x00;                     // 标准标识符为0
  TxMessage.ExtId=0x1234;                 // 设置扩展标示符(29位)
  TxMessage.IDE=CAN_ID_EXT;             // 使用扩展标识符
  TxMessage.RTR=CAN_RTR_DATA;         // 消息类型为数据帧,一帧8位
  TxMessage.DLC=2;                             // 发送两帧信息
  TxMessage.Data[0]=0xDE;                 // 第一帧信息
  TxMessage.Data[1]=0xCA;                 // 第二帧信息
  CAN_Transmit(CAN1, &TxMessage);

  /* initialize the value that will be returned */
  ret = 0xFF;
      
  /* receive message with interrupt handling */
  i=0;
  while((ret == 0xFF) && (i < 0xFFF))
  {
    i++;
  }
 
  if (i == 0xFFF)
  {
    ret=0; 
  }

  /* disable interrupt handling */
  CAN_ITConfig(CAN1, CAN_IT_FMP0, DISABLE);

  return (TestStatus)ret;
}
5、CAN的中断处理函数
检查是否接收到正确的消息。如果消息正确则设置标识符为1  否则设置为0
void USB_LP_CAN1_RX0_IRQHandler(void)
{
  CanRxMsg RxMessage;

  RxMessage.StdId=0x00;
  RxMessage.ExtId=0x00;
  RxMessage.IDE=0;
  RxMessage.DLC=0;
  RxMessage.FMI=0;
  RxMessage.Data[0]=0x00;
  RxMessage.Data[1]=0x00;

  CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);

  if((RxMessage.ExtId==0x1234) && (RxMessage.IDE==CAN_ID_EXT)
     && (RxMessage.DLC==2) && ((RxMessage.Data[1]|RxMessage.Data[0]<<8)==0xDECA))
  {
    ret = 1;
  }
  else
  {
    ret = 0;
  }
}


6、这个实验比zangchao的简单多了。只是完成了LoopBack,没有进行协议转换和双机通讯。还比较弱智的说


7、例行性的上图
CAN 回环数据串口监视

CAN LoopBack时的寄存器

查看系统寄存器的方法


工程师
2012-06-07 21:36:33     打赏
167楼
哈哈,能成功不错了。有个好消息啊,我的成功了,现在一直应用了,测试5天,要是没有问题,就完成了。

工程师
2012-06-07 21:39:49     打赏
168楼
可以用JLINK单步跟踪,这样就知道寄存器是如何变化的了,也就知道CAN的工作过程了。不过这个过程比较繁琐,而且还得需要动手分析,不过能够短时间了解工作原理。

高工
2012-06-08 10:22:26     打赏
169楼
体验硬件CRC

看看手册,STM32中有一个硬件CRC发生器。使用也比较简单:
1、开启CRC时钟
2、向CRC_DR寄存器中写入要计算的数据
3、从CRC_DR中读出数据

下边是代码:
1、初始化函数,开时钟
void CRC_Init(void)
{
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC, ENABLE);
}

2、计算数据块的CRC
    CRCValue = CRC_CalcBlockCRC((uint32_t *)DataBuffer, BUFFER_SIZE);    //计算一个数据块的CRC
按F12跟着进去,感觉这个CRC_CalcBlockCRC有问题。好像只返回了最后一个数据的CRC。并没有真正计算
  查看手册才发现有这样的描述:每一次写入数据寄存器,其计算结果是前一次CRC计算结果和新计算结果的组合(对整个32位字进行CRC计算,而不是逐字节地计算)。
  所以,计算结果就是这个样子的。
如果需要获得单独这组数据的计算结果,在计算之前应先使用CRC_ResetDR()复位CRC_DR寄存器。
3、计算单个数据的CRC
(1)寄存器方式
    CRC->DR = DataBuffer[i];             //计算一个数据的CRC
    CRCValue = CRC->DR;
(2)库函数方式
    CRCValue = CRC_CalcCRC(DataBuffer[i]);

对比两种方式结果是一样的
注:根据前面的说明,要获得单个数据的CRC,在计算前也要复位CRC_DR寄存器。
4、获得CRC结果后,可以使用printf将结果打印到电脑查看:
    printf("32-位数据 CRC 校验码为:0X%X\r\n", CRCValue);
4、要抓的图太多了。我想已经够明白了,不需要再贴图了

工程师
2012-06-08 12:03:44     打赏
170楼
哈哈,等有时间我也体验下,要保证通信可靠CRC挺基础的。

共191条 17/20 |‹ 15 16 17 18 19 20 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]