⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 针对arm开发板开发的can总线应用程序
💻 C
字号:
//  ----------------------------------------------------------------------------
//          ATMEL Microcontroller Software Support  -  ROUSSET  -
//  ----------------------------------------------------------------------------
//  DISCLAIMER:  THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
//  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
//  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
//  DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
//  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
//  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
//  OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
//  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ----------------------------------------------------------------------------
//  File Name           : main.c
//  Object              : main application written in C
//  Creation            : FBr   02-Sep-2005
// ----------------------------------------------------------------------------

#include "main.h"
/* Global variables */
volatile char       testCAN0 = AT91C_TEST_NOK;
volatile char       testCAN1 = AT91C_TEST_NOK;
extern  void CanSendData(unsigned int LData,unsigned HData) ;

//*----------------------------------------------------------------------------
//* \fn    AT91F_CAN0_Handler
//* \brief
//*----------------------------------------------------------------------------
void AT91F_CAN0_Handler(void)
{
  volatile unsigned int status;
		
  status = AT91F_CAN_GetStatus(AT91C_BASE_CAN0) & AT91F_CAN_GetInterruptMaskStatus(AT91C_BASE_CAN0);
  AT91F_CAN_DisableIt(AT91C_BASE_CAN0,status);
  int RxData=AT91F_CAN_GetMessageDataLow(&AT91C_BASE_CAN0->CAN_MB0) ;
  TRACE_INFO("______Interrupt now is received some data____________") ;
  TRACE_INFO("%d",RxData);
  if(status & AT91C_CAN_WAKEUP) {
    testCAN0 = AT91C_TEST_OK;
    TRACE_DEBUG_H("=> CAN0 WAKEUP ");
  }

}

//*----------------------------------------------------------------------------
//* \fn    AT91F_CAN1_Handler
//* \brief
//*----------------------------------------------------------------------------
void AT91F_CAN1_Handler(void)   //接收CAN0 ->MB0 发送的数据
{
  volatile unsigned int status;
  int RxData ;
		
  status = AT91F_CAN_GetStatus(AT91C_BASE_CAN1) & AT91F_CAN_GetInterruptMaskStatus(AT91C_BASE_CAN1);
  AT91F_CAN_DisableIt(AT91C_BASE_CAN1,status);

  RxData=AT91F_CAN_GetMessageDataLow(&AT91C_BASE_CAN1->CAN_MB0)  ;     //接收低四位
  TRACE_INFO("\r\n______Interrupt received  data,Low is:") ;
  TRACE_INFO("%d",RxData );
  RxData=AT91F_CAN_GetMessageDataHigh(&AT91C_BASE_CAN1->CAN_MB0) ;     //接收高四位
  TRACE_INFO("\r\n_______Interrupt received data,High is:") ;

  /**如果如下指令不执行的话,所有读出的数据都将是第一次接收到的数据**/
  AT91C_BASE_CAN1_MB0->CAN_MB_MCR=AT91C_CAN_MTCR;          //允许接收下一条消息
  /*******************************************************************/
  TRACE_INFO("%d",RxData );
  if((status & AT91C_CAN_WAKEUP) == AT91C_CAN_WAKEUP) {
    testCAN1 = AT91C_TEST_OK;
    TRACE_DEBUG_H("=> CAN1 WAKEUP ");
  }

}

//*--------------------------------------------------------------------------------------
//* Function Name       : Main
//* Object              : Software entry point

//* 主程序主要实现 CAN 在较低拨特率( 5K , 10K )下的通讯 ,主要工作在于设置正确的拨特率 ,
//* 由于在 MCK=48mHz的情况下不能得到如此低的拨特率,于是采用降低主频的方式。在 波特率为5K
//* 的测试条件下,将主频降为 6mHz ,即 MCK的8分频。得到分频数 BRP= 6m/5K/16 -1 =74= 0x4A ,
//* 现在的状态即为 MCK=6M, CAN baudrate= 5 k 的测试程序。调试串口输出的拨特率为 9600 。
//***************************************************************************************
//***************在测试 CAN baudrate= 10 k 的时候,仅需要改动几个如下部分而已************
//* 1。将MCK 4分频,降低为 12mHz,即将  AT91C_BASE_PMC->PMC_MCKR |=AT91C_PMC_PRES_CLK_8  ;
//*    改为  AT91C_BASE_PMC->PMC_MCKR |=AT91C_PMC_PRES_CLK_4  ;
//* 2。将 DBGU调试串口配置为 :波特率设置为 115200 ,主时钟为 AT91C_MASTER_CLOCK/2
//*    改动点在函数  AT91F_US_Configure(...)中
//* 3。CAN 波特率寄存器的值 : 频数 BRP= 12m/10K /16 -1 =74= 0x4A , 所有低波特率情况下,当
//*    CAN的传输延迟时间小于一个bit的时间时候,都可以 PROPAG=0 ,PHASE1= PHASE2=6。即 0x004A3066
//*    和 5K的时候一样。
//*********************************配置调试串口的一点注意********************************
//* 本测试程序在 10K 的时候设定波特率为 115200,却 在 5K的时候配置为9600 。按照串口的波特率
//* 计算公式 baudrate=MCK/16/ CD (CD为16 bit的波特率发生器寄存),5K 时,CD=6m/16/115200
//* =3.2552 似乎可行,但输出全是乱码, 原因在于当 CD小于 6.5的时候,波特率计算公式会根据不同的
//* 情况调整,可能得不到预期的值。最好大于6.5。(9600时,CD=39.0625)
//*--------------------------------------------------------------------------------------
void main()
{
  ////////////////////////////////////////////////////////////////////////////////////////////////////
  //   设置MCK ,can的时钟为 MCK ,如今MCK=48mHz ,为了降到5K的波特率,需要降低主时钟,现如今将MCK时钟
  //   降为原来的 8 分之一 ,现 MCK=6M ,
  ////////////////////////////////////////////////////////////////////////////////////////////////////
  AT91C_BASE_CKGR->CKGR_MOR=0x00000701 ;                 //时钟在56个慢时钟周期后启动
 //必须等待PMC_SR 寄存器中的MOSCS域置位,可通过轮询状态寄存器或等待当PMC_IER 寄存器中与MOSCS相关的中断的中断线上升
  //>>>>>
  unsigned int status ;
  do{                                                         //等待CKGR_MCFR寄存器中的MAINRDY域置位
     status=AT91C_BASE_CKGR->CKGR_MCFR ;
     status &= 0x00010000 ;
    }
  while(status!=0x10000);
                                                              //等待CKGR_MCFR寄存器中的MAINRDY域置位(下)

  do{
    status=AT91C_BASE_CKGR->CKGR_MCFR ;
    status &= 0x000010000 ;
    }
  while(status!=0x10000)  ;                                  //AT91C_BASE_CKGR->CKGR_MCFR=0x1FFFF   ;
    status=(AT91C_BASE_CKGR->CKGR_MCFR & 0x0FFFF) ;          //***读出16个慢时钟周期中主时钟周期数 ,没有使用

  AT91C_BASE_PMC->PMC_MCKR =AT91C_PMC_CSS_MAIN_CLK ;         //处理器时钟为主机时钟。 8分频
  AT91C_BASE_PMC->PMC_MCKR |=AT91C_PMC_PRES_CLK_8  ;         //此时 MCk=48/8 =6M
  do{
    status=AT91C_BASE_CKGR->CKGR_MCFR ;
    status &= 0x000010000 ;
    }
  while(status!=0x10000)  ;

  //AT91C_BASE_PMC->PMC_PCER=0xFFFFFFFF              ; //使能外设时钟(1,4,5,6,7,8)0x000001F2

 // AT91C_BASE_PMC->PMC_MCFR|=AT91C_CKGR_MAINF ;
 // AT91C_BASE_PMC->PMC_MCFR|=AT91C_CKGR_MAINRDY ;

/*
  AT91C_BASE_PMC->PMC_MCFR|=AT91C_CKGR_MAINF ;
  AT91C_BASE_PMC->PMC_MCFR|=AT91C_CKGR_MAINRDY ;
  AT91C_BASE_PMC->PMC_MOR |=AT91C_CKGR_MOSCEN  ;
  AT91C_BASE_PMC->PMC_MOR |=AT91C_CKGR_OSCOUNT ;
*/
//  AT91C_BASE_PMC->PMC_SCER |=AT91C_PMC_PCK ;


  /////////////////////////////////////////////////////////////////////////////////////////////////////
  // Enable DBGU Clock
  AT91F_DBGU_CfgPMC();    // DBGU is always clocked
  // Open PIO for DBGU
  AT91F_DBGU_CfgPIO();
  //在设置波特率的时候,当CD值为小于6.5的 ,系统的算法会进行调整,而得不到想要的值,请避开
  AT91F_US_Configure ((AT91PS_USART) AT91C_BASE_DBGU,
                      AT91C_MASTER_CLOCK/4,
                      AT91C_US_ASYNC_MODE,  	// mode Register to be programmed
                      9600,	                // ******baudrate to be programmedAT91C_BAUDRATE_115200
                      0);                   	// timeguard to be programmed
  // Enable Transmitter
  AT91F_US_EnableTx((AT91PS_USART) AT91C_BASE_DBGU);

  TRACE_INFO("\n\n\r======================================\n\r");
  TRACE_INFO("*****AT91SAM7A3 Basic CAN in 12mHz 10K 16bit Carry / 1 bit***** \n\r");
  TRACE_INFO("======================================\n\r");

  ///////////////////////////////////////////////////////////////////////////////////////////
  //  Init CAN0 and CAN1
  ///////////////////////////////////////////////////////////////////////////////////////////

  // Enable CAN0 and CAN1 PIOs
  AT91F_CAN0_CfgPIO();
  AT91F_CAN1_CfgPIO();
  // Enable CAN0 and CAN1 Clocks
  AT91F_CAN0_CfgPMC();
  AT91F_CAN1_CfgPMC();

  // Enable CANs Transceivers
  AT91F_PIOA_CfgPMC();
  AT91F_PIO_CfgOutput(AT91C_BASE_PIOA,AT91B_CAN_TRANSCEIVER_RS) ;
  // Clear PA23 <=> Enable Transceiver Normal Mode (versus Standby mode)
  AT91F_PIO_ClearOutput(AT91C_BASE_PIOA,AT91B_CAN_TRANSCEIVER_RS) ;

  // Init CAN0 Interrupt Source Level
  AT91F_AIC_ConfigureIt(AT91C_BASE_AIC,                        	// CAN0 base address
                        AT91C_ID_CAN0,                         	// CAN0 ID
                        AT91C_AIC_PRIOR_HIGHEST,               	// Max priority
                        AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, 	    // Level sensitive
                        AT91F_CAN0_Handler);                    // C Handler

  AT91F_AIC_EnableIt(AT91C_BASE_AIC,AT91C_ID_CAN0);

  // Init CAN1 Interrupt Source Level
  AT91F_AIC_ConfigureIt(AT91C_BASE_AIC,                        	// CAN1 base address
                        AT91C_ID_CAN1,                         	// CAN1 ID
                        AT91C_AIC_PRIOR_HIGHEST,               	// Max priority
                        AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, 	    // Level sensitive
                        AT91F_CAN1_Handler);                    // C Handler

  AT91F_AIC_EnableIt(AT91C_BASE_AIC,AT91C_ID_CAN1);             //AIC中断允许

  // Cfg CAN Baudrate to 1Mbit/s => BRP = 5
  // We choose 8 Time Quanta (tCSC = 125ns): 8tCSC = tSYNC + tPRS + tPHS1 + tPHS2
  // Cfg PHASE1 PHASE2 PROPAG and SYNC segment
  // Delay of busdriver + delay of receiver circuit = 200ns
  // Delay of bus line considered negligible = 0ns
  // tPRS = 2*(200+0) = 400ns < 4tCSC => PROPAG = 3
  // tSYNC = 1tCSC =>  8tCSC = 1tCSC + 4tCSC + tPHS1 + tPHS2
  // tPHS1 + tPHS2 = 3tCSC => Phase Segment 2 = Max(IPT=2TQ,Phase Segment 1) = 2TQ => PHASE2 = 2-1 = 1 => PHASE1 = 0
  // tSJW = Min(4 TQ, Phase Segment 1) = 1TQ => SJW = 1-1 = 0

  //AT91F_CAN_CfgBaudrateReg(AT91C_BASE_CAN0,0x007c3066);       //config 1D3066= 100K,相互通讯的两个CAN的拨特率必须相同
  //AT91F_CAN_CfgBaudrateReg(AT91C_BASE_CAN1,0x007c3066);       //0x007c3066=24k

  AT91F_CAN_CfgBaudrateReg(AT91C_BASE_CAN0,0x004A3066);       //当 MCK 变为12mHz时 ,10K=0x004A3066
  AT91F_CAN_CfgBaudrateReg(AT91C_BASE_CAN1,0x004A3066);
  //当频率变为 6MHz时候 ,5K =0x004A3066

  ///////////////////////////////////////////////////////////////////////////////////////////
  //  Enter Main Application
  ///////////////////////////////////////////////////////////////////////////////////////////

  AT91F_BasicTestSuite();            //进行一次测试

  for(;;)
  {
     /**以100K的速率由 CAN0->Mailbox0 向 Can1->Mailbox0 发送数据**/

      for(int n=0;n<=32767;)  //减慢发送速度,以使超级终端显示的数据让人眼睛看起来不闪烁
        for(int i=0;i<=30000;i++)
          for(int j=0;j<=12;j++)
           n++ ;

      static int datas=1 ;
      if(datas>=32767)
        datas=1 ;
      CanSendData((unsigned)(0x100),(unsigned)datas++) ;
   }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -