📄 main.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 + -