394

帖子

0

TA的资源

一粒金砂(高级)

61
 
最近还在构思,呵呵。新作将会继续更新。
此帖出自NXP MCU论坛
 

回复

928

帖子

0

TA的资源

五彩晶圆(高级)

62
 
学习一下,谢谢。
此帖出自NXP MCU论坛
 
个人签名动手创造个性自我

https://home.eeworld.com.cn/?95709
 
 

回复

394

帖子

0

TA的资源

一粒金砂(高级)

63
 

MDK+JLINKv7+LPC1343之攻略探讨交流(5月31日第7次更新,CAN总线外扩篇)

§ 531更新NO.7

其实由LPC1343的介绍可以看出这个芯片的功能上还是很强大的,现在我们来研究一下板载的通信方式如下图介绍的有USBUART485IICSPISSP)。这些都是硬件的通信接口,很常用,但是这个芯

片不带有以太网与CAN,这两个目前在控制行业很流行的通信接口,当然没有板载的并不意味着我们就比必须换片子。现在我将与大伙一起采用最成熟的方案扩展这些个接口。

        

扩展CAN接口,先了解下CAN接口的相关知识:CAN总线全称为Controller Area Network即控制器局域网是国际上应用最广泛的现场总线之一,已经在汽车制造、机械制造、包装机械、烟草等行业得到了广泛的应用。CAN总线是德国BOSCH公司从80年代初为解决现代汽车中众多的控制与测试仪器之间的数据交换而开发的一种串行数据通信协议,它是一种多主总线,通信介质可以是双绞线、同轴电缆或光导纤维。通信速率可达1MBPS。CAN总线通信接口中集成了CAN协议的物理层和数据链路层功能,可完成对通信数据的成帧处理,包括位填充、数据块编码、循环冗余检验、优先级判别等项工作。

 

CAN协议的一个最大特点是废除了传统的站地址编码,而代之以对通信数据块进行编码。采用这种方法的优点可使网络内的节点个数在理论上不受限制,数据块的标识码可由11位或29位二进制数组成,因此可以定义211或229个不同的数据块,这种按数据块编码的方式,还可使不同的节点同时接收到相同的数据,这一点在分布式控制系统中非常有用。数据段长度最多为8个字节,可满足通常工业领域中控制命令、工作状态及测试数据的一般要求。同时,8个字节不会占用总线时间过长,从而保证了通信的实时性。CAN协议采用CRC检验并可提供相应的错误处理功能,保证了数据通信的可靠性。CAN卓越的特性、极高的可靠性和独特的设计,特别适合工业过程监控设备的互连,因此,越来越受到工业界的重视,并已公认为最有前途的现场总线之一。

 

另外,CAN总线采用了多主竞争式总线结构,具有多主站运行和分散仲裁的串行总线以及广播通信的特点。CAN总线上任意节点可在任意时刻主动地向网络上其它节点发送信息而不分主次,因此可在各节点之间实现自由通信。CAN总线协议已被国际标准化组织认证,技术比较成熟,控制的芯片已经商品化,性价比高,特别适用于分布式测控系统之间的数通讯。CAN总线插卡可以任意插在PC、AT、XT兼容机上,方便地构成分布式监控系统。

 

CAN总线最成熟的方案算是飞利浦也就是LPC1343的老东家NXP的SJA1000方案,目前采用的原理图为下图之连接,该图有幸在Freescale平台上验证过,当时主时钟为40M,总线时钟采用的20M的环境。现在想采用LPC1343来做个移植,考虑到LPC1343的主频率可以达到72M最大的主时钟,希望能够提高CAN的通信总线速率。

 

此帖出自NXP MCU论坛
 
 
 

回复

394

帖子

0

TA的资源

一粒金砂(高级)

64
 

NO.7接续!

SJA1000与LPC1343的硬件连接为:


AD0~AD7数据口 ——PIO2.0~PIO2.7
CS—————————PIO1.10、
ALE———————— PIO1.9
RD ———————— PIO0.3
WR ———————— PIO0.1
INT ———————— PIO3.3(IO管脚中断)

由于LPC1343的内部总线接口没有引到外部,所以这里只有采用模拟总线的方式。也就是采用IO口的时序模拟总线,这里面最主要的就是处理好时钟、时序的问题。由于代码是跨平台的移植,个人觉得时序上没有需要更改的地方,但是在时钟上就得注意与SJA1000的匹配,不然通信的成功与稳定上就得商榷下。模拟总线先就得来了解下IO口操作的几个相关寄存器:
 
首先可以看到LPC1343一共有4个IO口,每个IO口有12个可用的管脚。同时相关的管脚存在功能上存在复用,这个一般的普通的单片机上都有。但是使用时一定要注意相关的管脚在电气结构上与一般的IO管脚是否有区别。就拿自己的实际教训来说,本来在开始我用LPC1343的管脚的时候我的硬件走线为:
CS—————————PIO0.4(I2C—SDA)、
ALE———————— PIO0.5(I2C—SCL)、
但是我实际信号上一直出现这两个管教无法抬升到高电平的现象,那个郁闷。我还在怀疑我的管教是不是设置错误,但是跑过去看,发现默然配置为普通的IO脚嘛!也没错啊,后来仔细的看手册才发现这两个角是开漏的方式输出,也就是要么选择配置为I2C的功能管教,要么为开漏输出的标准IO,使用时外部需要接上拉的。

这里面我们需要关注的是GPIOnDATAGPIOnDIRGPIOnISGPIOnIBEGPIOnIEVGPIOnIE。这里涉及到普通IO管脚的使用以及将普通管脚作为中断触发的使用方式。当然在程序里面,可能需要用到的有如下几个子函数:

void GPIOSetDir( uint32_t portNum, uint32_t bitPosi, uint32_t dir ) ;//管脚输出/入方式设定

void GPIOSetInterrupt( uint32_t portNum, uint32_t bitPosi, uint32_t sense,

                            uint32_t single, uint32_t event ) ; //管脚中断方式设置

void GPIOIntEnable( uint32_t portNum, uint32_t bitPosi ); //管脚中断使能

 

当然涉及到多个IO管教状态的转换时候用如下的方式更好:

LPC_GPIO2->DIR = 0xFF;    //默认先设定sja1000数据线为输出

LPC_GPIO2->DATA |= 0xFF;

这样可以直接对IO口的8跟数据线进行设置,呵呵。

 

此帖出自NXP MCU论坛
 
 
 

回复

394

帖子

0

TA的资源

一粒金砂(高级)

65
 

斑竹修改标题为:MDK+JLINKv7+LPC1343之攻略探讨交流(5月31日第7次更新,CAN总线外扩篇)

--------------------还没写完,主要是代码还在调试ing,先占个位先!@@

[ 本帖最后由 pepsi360 于 2010-5-31 11:25 编辑 ]
此帖出自NXP MCU论坛
 
 
 

回复

394

帖子

0

TA的资源

一粒金砂(高级)

66
 
发现我的硬件视乎出了点问题,明天再去换一下硬件。哎,一个芯片好像坏掉啦
此帖出自NXP MCU论坛
 
 
 

回复

3

帖子

0

TA的资源

一粒金砂(初级)

67
 
硬件问题??不会把开发板给短路了吧??还能够接着开工不啊???呵呵,期待你的新作~~~~
can总线也算个小应用,呵呵。
此帖出自NXP MCU论坛
 
 
 

回复

41

帖子

0

TA的资源

一粒金砂(初级)

68
 
学习了
此帖出自NXP MCU论坛
 
个人签名一生只做一件事
 
 

回复

41

帖子

0

TA的资源

一粒金砂(初级)

69
 
越看越有味道,收藏起来。
此帖出自NXP MCU论坛
 
个人签名一生只做一件事
 
 

回复

394

帖子

0

TA的资源

一粒金砂(高级)

70
 

CAN总线外扩接上续!

§ 6月2日更新NO.8

 

做这个CAN总线的扩展,采用模拟总线的方式,我们主要应用到IO口的两种功能,那就是常规的输入输出与IO口管脚中断功能。

下面对这两种功能运用到的寄存器与函数库中的内容作些许说明:
 IO口的常规输入输出应用:
       与这个功能相关的寄存器主要是GPIOnDATA、GPIOnDIR应用非常简单直接做样就可以
LPC_GPIO2->DIR = 0xFF;//为1的位则设置相应管教为输出模式   
LPC_GPIO2->DATA |= 0xFF; //为1的位则设置相应管教输出1
库函数的相关封装的函数如下可以结合的理解下这两个寄存器的功能。

 

/*****************************************************************************
** Function name:  GPIOSetDir
**
** Descriptions:  Set the direction in GPIO port
**
** parameters:   port num, bit position, direction (1 out, 0 input)
** Returned value:  None
**
*****************************************************************************/
void GPIOSetDir( uint32_t portNum, uint32_t bitPosi, uint32_t dir )
{
  /* if DIR is OUT(1), but GPIOx_DIR is not set, set DIR
  to OUT(1); if DIR is IN(0), but GPIOx_DIR is set, clr
  DIR to IN(0). All the other cases are ignored.
  On port3(bit 0 through 3 only), no error protection if
  bit value is out of range. */
  switch ( portNum )
  {
 case PORT0:
   if ( !(LPC_GPIO0->DIR & (0x1<<bitPosi)) && (dir == 1) )
  LPC_GPIO0->DIR |= (0x1<<bitPosi);
   else if ( (LPC_GPIO0->DIR & (0x1<<bitPosi)) && (dir == 0) )
  LPC_GPIO0->DIR &= ~(0x1<<bitPosi);  
 break;
  case PORT1:
   if ( !(LPC_GPIO1->DIR & (0x1<<bitPosi)) && (dir == 1) )
  LPC_GPIO1->DIR |= (0x1<<bitPosi);
   else if ( (LPC_GPIO1->DIR & (0x1<<bitPosi)) && (dir == 0) )
  LPC_GPIO1->DIR &= ~(0x1<<bitPosi);  
 break;
 case PORT2:
   if ( !(LPC_GPIO2->DIR & (0x1<<bitPosi)) && (dir == 1) )
  LPC_GPIO2->DIR |= (0x1<<bitPosi);
   else if ( (LPC_GPIO2->DIR & (0x1<<bitPosi)) && (dir == 0) )
  LPC_GPIO2->DIR &= ~(0x1<<bitPosi);  
 break;
 case PORT3:
   if ( !(LPC_GPIO3->DIR & (0x1<<bitPosi)) && (dir == 1) )
  LPC_GPIO3->DIR |= (0x1<<bitPosi);
   else if ( (LPC_GPIO3->DIR & (0x1<<bitPosi)) && (dir == 0) )
  LPC_GPIO3->DIR &= ~(0x1<<bitPosi);  
 break;
 default:
   break;
  }
  return;
}
可以发现基本上LPC_GPIOn->DIR是对这个的操作,也即是对GPIOnDIR的位设置,就实现哪个portNum的哪个bitPosi位的dir方向。较易理解。

 


/*****************************************************************************
** Function name:  GPIOSetValue
**
** Descriptions:  Set/clear a bitvalue in a specific bit position
**      in GPIO portX(X is the port number.)
**
** parameters:   port num, bit position, bit value
** Returned value:  None
**
*****************************************************************************/
void GPIOSetValue( uint32_t portNum, uint32_t bitPosi, uint32_t bitVal )
{
  /* if bitVal is 1, the bitPosi bit is set in the GPIOShadowPortx. Then
   * GPIOShadowPortx is written to the I/O port register. */
  switch ( portNum )
  {
 case PORT0:
   if(bitVal)
  GPIOShadowPort0 |= (1<<bitPosi);
   else
  GPIOShadowPort0 &= ~(1<<bitPosi);

   /* Use of shadow prevents bit operation error if the read value
   * (external hardware state) of a pin differs from the I/O latch
   * value. A potential side effect is that other GPIO code in this
   * project that is not aware of the shadow will have its GPIO
   * state overwritten.
   */
  LPC_GPIO0->DATA = GPIOShadowPort0;
 break;
  case PORT1:
  if(bitVal)
   GPIOShadowPort1 |= (1<<bitPosi);
  else
   GPIOShadowPort1 &= ~(1<<bitPosi);

  LPC_GPIO1->DATA = GPIOShadowPort1;
 break;
 case PORT2:
  if(bitVal)
   GPIOShadowPort2 |= (1<<bitPosi);
  else
   GPIOShadowPort2 &= ~(1<<bitPosi);

  LPC_GPIO2->DATA = GPIOShadowPort2;
 break;
 case PORT3:
  if(bitVal)
   GPIOShadowPort3 |= (1<<bitPosi);
  else
   GPIOShadowPort3 &= ~(1<<bitPosi);

  LPC_GPIO3->DATA = GPIOShadowPort3;
 break;
 default:
   break;
  }
  return;
}
可以发现基本上是对LPC_GPIOn->DATA寄存器的操作,以完成数据的输出。也不难理解,也就是GPIOnDATA、GPIOnDIR两个寄存器可以实现

 

IO口的管脚中断应用:
    设置IO口的管脚中断其实主要相关的寄存器是GPIOnIS、GPIOnIBE、GPIOnIEV。


/*****************************************************************************
** Function name:  GPIOSetInterrupt
**
** Descriptions:  Set interrupt sense, event, etc.
**      edge or level, 0 is edge, 1 is level
**      single or double edge, 0 is single, 1 is double
**      active high or low, etc.
**
** parameters:   port num, bit position, sense, single/doube, polarity
** Returned value:  None
**
*****************************************************************************/
void GPIOSetInterrupt( uint32_t portNum, uint32_t bitPosi, uint32_t sense,
   uint32_t single, uint32_t event )
{
  switch ( portNum )
  {
 case PORT0:
   if ( sense == 0 )
   {
  LPC_GPIO0->IS &= ~(0x1<<bitPosi);
  /* single or double only applies when sense is 0(edge trigger). */
  if ( single == 0 )
    LPC_GPIO0->IBE &= ~(0x1<<bitPosi);
  else
    LPC_GPIO0->IBE |= (0x1<<bitPosi);
   }
   else
    LPC_GPIO0->IS |= (0x1<<bitPosi);
   if ( event == 0 )
  LPC_GPIO0->IEV &= ~(0x1<<bitPosi);
   else
  LPC_GPIO0->IEV |= (0x1<<bitPosi);
 break;
 
。。。。。。。。。。。。。。。。。。
case PORT1://同上
。。。。。。。。。。。。。。。。。。
case PORT2: //同上
。。。。。。。。。。。。。。。。。。
case PORT3: //同上
。。。。。。。。。。。。。。。。。。
 
  }
  return;
}
这个函数就是依据如下:
GPIOnIS—位为0设置为边沿触发,位为1设置为电平触发。
GPIOnIBE--位为0设置为单状态触发(一种边沿状态或电平状态)由IEV决定,位为1设置为双边沿触发。
GPIOnIEV--位为0设置为下降沿或低电平触发,位为1设置为上升沿或高电平触发。

 

 

/*****************************************************************************
** Function name:  GPIOIntEnable
**
** Descriptions:  Enable Interrupt Mask for a port pin.
**
** parameters:   port num, bit position
** Returned value:  None
**
*****************************************************************************/
void GPIOIntEnable( uint32_t portNum, uint32_t bitPosi )
{
  switch ( portNum )
  {
 case PORT0:
   LPC_GPIO0->IE |= (0x1<<bitPosi);
 break;
  case PORT1:
   LPC_GPIO1->IE |= (0x1<<bitPosi);
 break;
 case PORT2:
   LPC_GPIO2->IE |= (0x1<<bitPosi);    
 break;
 case PORT3:
   LPC_GPIO3->IE |= (0x1<<bitPosi);    
 break;
 default:
   break;
  }
  return;
}
可以发现基本上是对GPIOnIE寄存器的设置:
GPIOnIE—位为0设置为中断被屏蔽,位为1设置为中断开启。

[[i] 本帖最后由 pepsi360 于 2010-6-2 11:41 编辑 [/i]]
此帖出自NXP MCU论坛
 
 
 

回复

394

帖子

0

TA的资源

一粒金砂(高级)

71
 

NO.8接续!

这样我们就算是为总线模拟的IO使用上扫清了障碍。我想仔细看看手册,没什么大问题啦!

下面我们来定义即将使用到的IO口的设置:
/*CAN端口配置*/
  GPIOSetDir( PORT3, 0, 1 );//sja1000_WR P3.1
  GPIOSetDir( PORT3, 1, 1 );//sja1000_RD P31

  GPIOSetDir( PORT1, 9, 1 );//sja1000_ALE P1.9
  GPIOSetDir( PORT1, 10, 1 );//sja1000_CS P1.10

/*默认先设定sja1000数据线为输出 */
  LPC_GPIO2->DIR = 0xFF;   
  LPC_GPIO2->DATA |= 0xFF;

  /*设置中断管教P3.3的输入属性*/
  GPIOSetDir( PORT3, 3, 0 );
  GPIOSetInterrupt(PORT3, 3, 0, 0, 0);
//第一个0表示边沿触发,第二个0表示单边沿触发, 第三个1表示负跳变触发
  GPIOIntEnable(PORT3, 3);

//打开IO中断功能
这样就把要使用的IO口的分配工作完成了。

今天就到这里啊!OVER,下篇再接着讲@@

[ 本帖最后由 pepsi360 于 2010-6-2 11:43 编辑 ]
此帖出自NXP MCU论坛
 
 
 

回复

394

帖子

0

TA的资源

一粒金砂(高级)

72
 
不知道这样的一种交流形式,大伙有什么意见或建议的,给我提一下,谢谢!也好决定本贴更新的方向。希望大伙积极的提点建议!
此帖出自NXP MCU论坛
 
 
 

回复

536

帖子

0

TA的资源

五彩晶圆(初级)

73
 
这样做的很不错。支持!
此帖出自NXP MCU论坛
 
 
 

回复

41

帖子

0

TA的资源

一粒金砂(中级)

74
 
:D
占个位置慢慢看
此帖出自NXP MCU论坛
 
 
 

回复

394

帖子

0

TA的资源

一粒金砂(高级)

75
 

原帖由 jolyku 于 2010-6-4 09:54 发表 :D 占个位置慢慢看

:L ,本贴拒绝占位,只接受建议与批评,嘿嘿!留下你的问题,让我痛苦去吧!

此帖出自NXP MCU论坛
 
 
 

回复

3

帖子

0

TA的资源

一粒金砂(初级)

76
 
神贴,怎么没人看啊??没有这篇开山之作,我想大伙上手都没好的路径的,收藏啦。
此帖出自NXP MCU论坛
 
 
 

回复

394

帖子

0

TA的资源

一粒金砂(高级)

77
 

本贴因为不可抗拒的原因,目前将暂停更新。如果广大爱好者有相关问题亦或是疑问的话,可以站送亦或是到如下群提问!@@

 

NXP Cortex M0/M3交流群,欢迎广大Cortex M0/M3的新人一起学习交流。

都是新手一起学习下!


NXP Cortex M0/M3交流群,欢迎广大Cortex M0/M3的新人一起学习,本人正在使用LPC1343,欢迎广大NXP的FANS 们一起来研究学习,欢迎ZLG开发平台的朋友一起进群交流。


有使用如下平台的朋友一起学习:


SmartCortex M3-1700


EasyCortex M3-1752


EasyCortex M3-1300开发平台
群号为:87394268管理方式上参考本群姊妹群的管理方式。

[ 本帖最后由 pepsi360 于 2010-6-8 12:04 编辑 ]
此帖出自NXP MCU论坛
 
 
 

回复

826

帖子

0

TA的资源

一粒金砂(中级)

78
 

PDF指导的对吗?

MDK+JLINKV8可以吗?
此帖出自NXP MCU论坛
 
 
 

回复

394

帖子

0

TA的资源

一粒金砂(高级)

79
 

原帖由 lilong8470 于 2010-6-8 17:14 发表 MDK+JLINKV8可以吗?

肯定可以啦,呵呵。按照前面的步骤来就没问题啦。

此帖出自NXP MCU论坛
 
 
 

回复

394

帖子

0

TA的资源

一粒金砂(高级)

80
 

§ 6月11日更新NO.9

前期的CAN总线的IO口的讲解以及分配任务做完以后呢,其实关于SJA1000的代码移植工作早已经完成平台的过渡工作,但是一直调试的不是很顺利,所以迟迟没有做相关的跟新。虽然前面说过不再做其他的相关更新,但是这个已经做了的工作还是整理一下,算是将前期的工作做个总结,做到有始有终。
CAN总线的代码主要分为5个函数:
uchar CanInit(void);
void CanSend(uchar *bufDATA,uchar datalen);
void WR_SJA(uchar sja_addr,uchar sja_data);
uchar RD_SJA(uchar sja_addr);
void INT_CAN_Receive(void);

/******************************************************************************************************************************************************
*函数名:CanInit(void)
*功能描述:CAN的初始化设置,在复位模式下设置CAN为单滤波,正常模式,PeliCAN模式,不屏蔽,8*     字节数据位
*函数说明: 通过ALE,RD,CS的配合控制完成
*调用函数:NONE
*全局变量:NONE
*输入:
*返回:
*设计者:
******************************************************************************************************************************************************/ 
uchar CanInit(void)
{
 uchar tempMode;
 volatile uchar temp7=0;
 volatile uchar temp8=0;
 uint Timeout=2000;

    tempMode =0x01;     //复位模式
tempMode |=0x00;     //设置CAN为双滤波 ,选择单个验收滤波器(16位长度)
    tempMode |=0x08;    //设置为单滤波模式
   
/************初始量付初值*********************************************/
 MaxLenCanRxBuf=260;//没有初始化,造成地址溢出,返回值全ff。
 CanRxAddr=0;
 CanRxcompleteFlag = 0;
 SendBufInfo=0;
 mSendDelay=0;
 
/*********************************************************/ 
    while( (temp7&0x01)==0 )
    {
    WR_SJA(SJA_MOD,tempMode);   //模式寄存器 进入复位模式 设定为单滤波
    temp7 = RD_SJA(SJA_MOD);    //设置的变量用来查看前面的写入是否成功。
    if(Timeout--==0)
    return (CAN_INIT_ERR);
    }  
    WR_SJA(SJA_CDR,0xC8);//时钟分频 选择PeliCAN模式 终止can输入比较器关闭时钟输出CLKOUT
    temp8=RD_SJA(SJA_CDR);
    WR_SJA(SJA_AMR0,0xff);  //验收屏蔽位设置,不影响
    WR_SJA(SJA_AMR1,0xff);
    WR_SJA(SJA_AMR2,0xff);
   WR_SJA(SJA_AMR3,0xff);

   WR_SJA(SJA_ACR0,0x80);     //验收代码位设置 扩展祯 数据 8字节
   WR_SJA(SJA_ACR1,0x00);
   WR_SJA(SJA_ACR2,0x00);
   WR_SJA(SJA_ACR3,0x00);
/******************************************************************************/ 
 temp7 = RD_SJA(SJA_MOD);
     temp7 = (temp7&0x01);//为1则说明进入工作模式,这样对OCR的写入没有任何意义
     while( (temp7&0x01)==0 )//为0则为工作模式
        {
        WR_SJA(SJA_MOD,tempMode);//写寄存器 进入复位模式
        temp7 = RD_SJA(SJA_MOD);
        if(Timeout--==0)
        return (CAN_INIT_ERR);
        }  
/*************************************************/
    WR_SJA(SJA_BTR0,0x00);          //设置CAN波特率为500k 通过波特率计算器可以算出该值
 WR_SJA(SJA_BTR1,0x1C);
 temp7 = RD_SJA(SJA_BTR0);
 temp8 = RD_SJA(SJA_BTR1);
 mSendDelay = 1000;
 WR_SJA(SJA_IER,0x01);   //中断允许 打开接收中断使能
 temp7 = RD_SJA(SJA_IER);
    Timeout=2000;
    do{
       temp7 = RD_SJA(SJA_MOD);
       temp7 = (temp7&0x01);//为1则说明进入工作模式,这样对OCR的写入没有任何意义
       while( (temp7&0x01)==0 )//为0则为工作模式
            {
            WR_SJA(SJA_MOD,tempMode);//写寄存器 进入复位模式
            temp7 = RD_SJA(SJA_MOD);
            if(Timeout--==0)
            return (CAN_INIT_ERR);
            }  
    WR_SJA(SJA_OCR,0x1a);  //输出控制 驱动上拉 正常输出模式
      temp7 = RD_SJA(SJA_OCR);
        if(Timeout--==0)
        return (CAN_INIT_ERR);
        }

    while( temp7!=0x1a );
    Timeout=2000;
    do{
       WR_SJA(SJA_MOD,tempMode&0xFE);//模式寄存器  退出复位模式
     temp7 = RD_SJA(SJA_MOD);
       temp7 = (temp7&0x01);
       if(Timeout--==0)
       return (CAN_INIT_ERR);
        }
    while( temp7!=0 );
    return (CAN_INIT_OK);
}
/******************************************************************************************************************************************************
*函数名:CanSend(uchar *bufDATA,uchar datalen)
*功能描述:Can设备数据发送函数
*函数说明:
*调用函数:NONE
*全局变量:NONE
*输入:
*返回:
*设计者:
******************************************************************************************************************************************************/ 
void CanSend(uchar *bufDATA,uchar datalen)
{
 uchar sja_addr;
 uchar j=0;
uchar temp;      //局部变量
     uint n;
/**********发送帧信息位与标示符区*******************/ 
 sja_addr=SJA_EFF;      //取SJA的ID号的首地址地址,ID0的地址。
 //   EFF_SFF_flag=0---->标准帧
     if(EFF_SFF_flag==0)
        {
        SendBufInfo=datalen;                    //填入数据长度信息
        WR_SJA(sja_addr++,SendBufInfo);         //以标准帧发送消息
        for(j=0; j<2; j++) //2字节的id信息到识别码1起始的地址,扩展帧与标准帧的区别在这里自己构建
        WR_SJA(sja_addr+j,*(SendBufId+j));  //发送2字节的id信息。
        for(j=0; j<datalen; j++)
     WR_SJA(sja_addr+2+j,*(bufDATA+j)); //发送data区数据。
        }
    //    EFF_SFF_flag=1---->扩展帧
       else if(EFF_SFF_flag==1)
        {
        SendBufInfo=datalen;                    //填入数据长度信息
        SendBufInfo |= 0x80;                    //添加扩展帧标示信息
        WR_SJA(sja_addr++,SendBufInfo);         //写带扩展帧信息的信息状态位
        for(j=0; j<4; j++)//4字节的id信息到识别码1起始的地址,扩展帧与标准帧的区别在这里自己构建
        WR_SJA(sja_addr+j,*(SendBufId+j));  //发送4字节的id信息。
        for(j=0; j<datalen; j++)
     WR_SJA(sja_addr+4+j,*(bufDATA+j)); //发送data区数区,在sja_addr+4+j起始处写入。
        }
/******************************************/
 WR_SJA(SJA_CMR,0x01); //打开发送请求位与终止发送位,Send 自动重发模式处理消息仲裁
 for(n=0;n<mSendDelay;n++)
 {
  temp=RD_SJA(SJA_SR);    //读取状态寄存器SR.3--TCS发送完毕状态 1(完毕)
  if((temp &0x08) == 0x08)    //发送完毕
  {
   for(n=0;n<300;n++);    //延时
   break; 
  }
 }
}

此帖出自NXP MCU论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条
Microchip 直播|利用motorBench开发套件高效开发电机磁场定向控制方案 报名中!
直播主题:利用motorBench开发套件高效开发电机磁场定向控制方案
直播时间:2025年3月25日(星期二)上午10:30-11:30
快来报名!

查看 »

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表