程序:
[plain] view plaincopy在CODE上查看代码片派生到我的代码片
/************************************
标题:操作CAN的练习
软件平台:IAR for ARM6.21
硬件平台:stm32f4-discovery
主频:168M
描述:通过硬件收发器连接CAN1,CAN2
组成一个两个端点的网络
CAN1循环发出数据帧
CAN2接收过滤数据帧
用uart把CAN2接收到
的数据帧发到超级终端
author:小船
data:2012-08-14
*************************************/
#include <stm32f4xx.h>
#include "MyDebugger.h"
#define RECEIVE_BUFFER_SIZE 20
u32 CAN2_receive_buffer[RECEIVE_BUFFER_SIZE][4];
u8 UART_send_buffer[1800];
u8 Consumer = 0;
u8 Producer = 0;
u32 Gb_TimingDelay;
void Delay(uint32_t nTime);
void TIM7_init();//定时1s
u32 get_rece_data();
void CAN_GPIO_config();
void main ()
{
u32 empty_box;
SysTick_Config(SystemCoreClock / 1000); //设置systemtick一毫秒中断
SCB->AIRCR = 0x05FA0000 | 0x400; //中断优先级分组 抢占:响应=3:1
MyDebugger_Init();
TIM7_init();
MyDebugger_Message( "\n\rtesting......\n\r" ,
sizeof("\n\rtesting......\n\r")/sizeof(char) );
CAN_GPIO_config();
RCC->APB1ENR |= ((1<<25)|(1<<26));//使能CAN1、CAN2时钟
CAN1->MCR = 0x00000000;
/*
请求进入初始化模式
禁止报文自动重传
自动唤醒模式
*/
CAN1->MCR |= ((1<<0)|(1<<4)|(1<<5));
CAN1->MCR &= ~(1<<16);//在调试时,CAN照常工作
while(!(CAN1->MSR & 0xfffffffe)) //等待进入初始化模式
{
MyDebugger_LEDs(orange, on);
}
MyDebugger_LEDs(orange, off);
/*
正常模式
重新同步跳跃宽度(1+1)tq
TS2[2:0]=3
TS1[3:0]=8
BRP[9:0]=2
ps:
tq = (BRP[9:0] + 1) x tPCLK,
tBS2 = tq x (TS2[2:0] + 1),
tBS1 = tq x (TS1[3:0] + 1),
NominalBitTime = 1 × tq+tBS1+tBS2,
BaudRate = 1 / NominalBitTime
波特率设为1M
*/
CAN1->BTR = ((0<<30)|(0x01<<24)|(3<<20)|(8<<16)|(2<<0));
CAN1->MCR &= ~(0x00000001);//正常工作模式
CAN2->MCR = 0x00000000;
/*
请求进入初始化模式
禁止报文自动重传
自动唤醒模式
*/
CAN2->MCR |= ((1<<0)|(1<<4)|(1<<5));
CAN2->MCR &= ~(1<<16);//在调试时,CAN照常工作
while(!(CAN2->MSR & 0xfffffffe)) //等待进入初始化模式
{
MyDebugger_LEDs(orange, on);
}
MyDebugger_LEDs(orange, off);
/*
正常模式
重新同步跳跃宽度(1+1)tq
TS2[2:0]=3
TS1[3:0]=8
BRP[9:0]=2
ps:
tq = (BRP[9:0] + 1) x tPCLK,
tBS2 = tq x (TS2[2:0] + 1),
tBS1 = tq x (TS1[3:0] + 1),
NominalBitTime = 1 × tq+tBS1+tBS2,
BaudRate = 1 / NominalBitTime
波特率设为1M
*/
CAN2->BTR = ((0<<30)|(0x01<<24)|(3<<20)|(8<<16)|(2<<0));
CAN2->IER &= 0x00000000;
/*
FIFO1消息挂号中断使能
FIFO1满中断使能
FIFO1溢出中断使能
*/
CAN2->IER |= ((1<<4)|(1<<5)|(1<<6));
NVIC->IP[65] = 0xa0; //抢占优先级101,响应优先级0
NVIC->ISER[2] |= (1<<1); //使能中断线65,也就是can2_rx1中断
CAN2->MCR &= ~(0x00000001);//正常工作模式
//总共有28组过滤器
CAN1->FMR |= 1; //过滤器组工作在初始化模式
CAN1->FMR &= 0xffffc0ff;//CAN2的过滤器组从14开始
CAN1->FMR |= (14<<8);
CAN1->FM1R |= (1<<14);//过滤器组14的寄存器工作在标识符列表模式
//位宽为16位,2个32位分为四个16位寄存器,过滤四个标识符
//CAN1->FS1R |= (1<<15);//过滤器组15为单个32位寄存器,用于扩展标识符
CAN1->FFA1R = 0x0fffc000;//0~13号过滤器组关联到fifo0,14~27号过滤器组关联到fifo1
CAN1->FA1R &= ~(1<<14);//禁用过滤器组14
/*
过滤器组0寄存器分为4个十六位过滤器:
标识符列表:
过滤器编号 匹配标准标识符 RTR IDE EXID[17:15]
0 0x7cb(111 1100 1011b) 数据帧 标准标识符 000b
1 0x4ab(100 1010 1011b) 数据帧 标准标识符 000b
2 0x7ab(111 1010 1011b) 数据帧 标准标识符 000b
3 0x40b(100 0000 1011b) 数据帧 标准标识符 000b
*/
CAN1->sFilterRegister[14].FR1 &= 0x00000000;
CAN1->sFilterRegister[14].FR2 &= 0x00000000;
CAN1->sFilterRegister[14].FR1 |= ((0x7cb<<5)|(0<<4)|(0<<3));
CAN1->sFilterRegister[14].FR1 |= ((0x4ab<<21)|(0<<20)|(0<<19));
CAN1->sFilterRegister[14].FR2 |= ((0x7ab<<5)|(0<<4)|(0<<3));
CAN1->sFilterRegister[14].FR2 |= ((0x40b<<21)|(0<<20)|(0<<19));
CAN1->FA1R |= (1<<14);//使能过滤器组14
CAN1->FMR &= ~1; //过滤器组正常工作
while(1)
{
/*
选择空的发送邮箱:
标准标识符0x7ab(111 1010 1011b)
数据帧
不使用扩展标识符
*/
if( CAN1->TSR & ((1<<26)|(1<<27)|(1<<28)) )
{
empty_box = ((CAN1->TSR>>24) & 0x00000003);
CAN1->sTxMailBox[empty_box].TIR = (0x7ab<<21);
CAN1->sTxMailBox[empty_box].TDTR &= 0xfffffff0;
CAN1->sTxMailBox[empty_box].TDTR |= 0x00000008;//发送数据长度为8
CAN1->sTxMailBox[empty_box].TDLR = 0x12345678;
CAN1->sTxMailBox[empty_box].TDHR = 0x9abcdef0;
CAN1->sTxMailBox[empty_box].TIR |= (1<<0);//请求发送
}
else
{
MyDebugger_LEDs(orange, on);
}
Delay(100);
/*
选择空的发送邮箱:
标准标识符0x4ab(100 1010 1011b)
数据帧
不使用扩展标识符
*/
if( CAN1->TSR & ((1<<26)|(1<<27)|(1<<28)) )
{
empty_box = ((CAN1->TSR>>24) & 0x00000003);
CAN1->sTxMailBox[empty_box].TIR = (0x4ab<<21);
CAN1->sTxMailBox[empty_box].TDTR &= 0xfffffff0;
CAN1->sTxMailBox[empty_box].TDTR |= 0x00000008;//发送数据长度为8
CAN1->sTxMailBox[empty_box].TDLR = 0x56781234;
CAN1->sTxMailBox[empty_box].TDHR = 0x9abcdef0;
CAN1->sTxMailBox[empty_box].TIR |= (1<<0);//请求发送
}
else
{
MyDebugger_LEDs(orange, on);
}
Delay(100);
/*
选择空的发送邮箱:
标准标识符0x7cb(100 1010 1011b)
数据帧
不使用扩展标识符
*/
if( CAN1->TSR & ((1<<26)|(1<<27)|(1<<28)) )
{
empty_box = ((CAN1->TSR>>24) & 0x00000003);
CAN1->sTxMailBox[empty_box].TIR = (0x7cb<<21);
CAN1->sTxMailBox[empty_box].TDTR &= 0xfffffff0;
CAN1->sTxMailBox[empty_box].TDTR |= 0x00000006;//发送数据长度为6
CAN1->sTxMailBox[empty_box].TDLR = 0x56781234;
CAN1->sTxMailBox[empty_box].TDHR = 0x00009abc;
CAN1->sTxMailBox[empty_box].TIR |= (1<<0);//请求发送
}
else
{
MyDebugger_LEDs(orange, on);
}
Delay(100);
/*
选择空的发送邮箱:
标准标识符0x40b(100 0000 1011b)
数据帧
不使用扩展标识符
*/
if( CAN1->TSR & ((1<<26)|(1<<27)|(1<<28)) )
{
empty_box = ((CAN1->TSR>>24) & 0x00000003);
CAN1->sTxMailBox[empty_box].TIR = (0x40b<<21);
CAN1->sTxMailBox[empty_box].TDTR &= 0xfffffff0;
CAN1->sTxMailBox[empty_box].TDTR |= 0x00000004;//发送数据长度为4
CAN1->sTxMailBox[empty_box].TDLR = 0x56781234;
CAN1->sTxMailBox[empty_box].TDHR = 0x00000000;
CAN1->sTxMailBox[empty_box].TIR |= (1<<0);//请求发送
}
else
{
MyDebugger_LEDs(orange, on);
}
Delay(100);
}
}
/****************************************
函数名:CAN_GPIO_config
参数:无
返回值:无
功能:设置CAN1,2控制器用到IO口
CAN1_TX---------PD1
CAN1_RX---------PB8
CAN2_TX---------PB13
CAN2_RX---------PB5
****************************************/
void CAN_GPIO_config()
{
RCC->AHB1ENR |= ((1<<1) | (1<<3));//使能GPIOB、D时钟
GPIOB->AFR[0] |= 0x00900000; //AF9
GPIOB->AFR[1] |= 0x00900009;
GPIOD->AFR[0] |= 0x00000090;
GPIOB->MODER &= 0xF3FCF3FF; //第二功能
GPIOB->MODER |= 0x08020800;
GPIOD->MODER &= 0xFFFFFFF3;
GPIOD->MODER |= 0x00000008;
GPIOB->OSPEEDR &= 0xF3FCF3FF; //50M
GPIOB->OSPEEDR |= 0x08020800;
GPIOD->OSPEEDR &= 0xFFFFFFF3;
GPIOD->OSPEEDR |= 0x00000008;
GPIOB->PUPDR &= 0xF3FCF3FF; //上拉
GPIOB->PUPDR |= 0x04010400;
GPIOD->PUPDR &= 0xFFFFFFF3;
GPIOD->PUPDR |= 0x00000004;
}
/****************************************
函数名:CAN2_RX1_IRQHandler
参数:无
返回值:无
功能:CAN2fifo1接收中断处理
把信息存进循环队列
****************************************/
void CAN2_RX1_IRQHandler()
{
if(CAN2->RF1R & (0x00000003))//接收到新的消息,fifo1非空
{
Producer++;
if(Producer == RECEIVE_BUFFER_SIZE)Producer = 0;
if(Producer != Consumer)
{
CAN2_receive_buffer[Producer][0] = CAN2->sFIFOMailBox[1].RIR;
CAN2_receive_buffer[Producer][1] = CAN2->sFIFOMailBox[1].RDTR;
CAN2_receive_buffer[Producer][2] = CAN2->sFIFOMailBox[1].RDLR;
CAN2_receive_buffer[Producer][3] = CAN2->sFIFOMailBox[1].RDHR;
}
else
{
if(Producer == 0)Producer = RECEIVE_BUFFER_SIZE;
Producer--;
MyDebugger_LEDs(blue, on);
}
CAN2->RF1R |= (1<<5);//释放邮箱
}
if(CAN2->RF1R & (1<<3))//fifo0满
{
MyDebugger_LEDs(red, on);
CAN2->RF1R &= ~(1<<3);
}
if(CAN2->RF1R & (1<<4))//fifo0溢出
{
MyDebugger_LEDs(red, on);
CAN2->RF1R &= ~(1<<4);
}
}
/****************************************
函数名:TIM7_init
参数:无
返回值:无
功能:初始化定时器7
作1s定时用
****************************************/
void TIM7_init()
{
RCC->APB1ENR |= (1<<5); //打开TIM7时钟
TIM7->PSC = 8399; //对时钟84M进行8400分频,使得计数频率为10k
TIM7->ARR = 10000; //定时一秒
TIM7->CNT = 0; //清空计数器
TIM7->CR1 |= (1<<7); //自动重装载预装载使能
TIM7->DIER |= 1; //使能中断
NVIC->IP[55] = 0xe0;
NVIC->ISER[1] |= (1<<(55-32));
TIM7->CR1 |= 1; //开始计时
}
/****************************************
函数名:TIM7_IRQHandler
参数:无
返回值:无
功能:定时器7中断处理
1s定时到
把can2收到的信息转换格式
用usrt发送到超级终端显示
****************************************/
void TIM7_IRQHandler(void)
{
u32 length;
if(TIM7->SR)
{
length = get_rece_data();
MyDebugger_Message( UART_send_buffer, length );
TIM7->SR &= ~(0x0001);
}
}
/****************************************
函数名:get_rece_data
参数:无
返回值:length 整理后要发送数据的长度
功能:把循环队列的信息取出
进行格式转换
把信息存到uart发送缓冲区
****************************************/
u32 get_rece_data()
{
u8 filter_No;
u8 Data_length;
char i;
u32 length = 0;
const char ascii[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
while(1)
{
if(Producer != Consumer)
{
Consumer++;
if(Consumer == RECEIVE_BUFFER_SIZE)Consumer=0;
UART_send_buffer[length++] = '\n';
UART_send_buffer[length++] = '\r';
//Filter No.xx
UART_send_buffer[length++] = 'F';
UART_send_buffer[length++] = 'i';
UART_send_buffer[length++] = 'l';
UART_send_buffer[length++] = 't';
UART_send_buffer[length++] = 'e';
UART_send_buffer[length++] = 'r';
UART_send_buffer[length++] = ' ';
UART_send_buffer[length++] = 'N';
UART_send_buffer[length++] = 'o';
UART_send_buffer[length++] = '.';
filter_No = (CAN2_receive_buffer[Consumer][1]>>8) & 0x000000ff;
UART_send_buffer[length++] = filter_No%100/10 + '0';
UART_send_buffer[length++] = filter_No%10 + '0';
UART_send_buffer[length++] = '\n';
UART_send_buffer[length++] = '\r';
//DataLength:x
UART_send_buffer[length++] = 'D';
UART_send_buffer[length++] = 'a';
UART_send_buffer[length++] = 't';
UART_send_buffer[length++] = 'a';
UART_send_buffer[length++] = 'L';
UART_send_buffer[length++] = 'e';
UART_send_buffer[length++] = 'n';
UART_send_buffer[length++] = 'g';
UART_send_buffer[length++] = 't';
UART_send_buffer[length++] = 'h';
UART_send_buffer[length++] = ':';
Data_length = CAN2_receive_buffer[Consumer][1] & 0x0000000f;
UART_send_buffer[length++] = Data_length % 10 + '0';
UART_send_buffer[length++] = '\n';
UART_send_buffer[length++] = '\r';
if(CAN2_receive_buffer[Consumer][0] & (1<<1))
{
UART_send_buffer[length++] = 'R';
UART_send_buffer[length++] = 'e';
UART_send_buffer[length++] = 'm';
UART_send_buffer[length++] = 'o';
UART_send_buffer[length++] = 't';
UART_send_buffer[length++] = 'e';
UART_send_buffer[length++] = 'F';
UART_send_buffer[length++] = 'r';
UART_send_buffer[length++] = 'a';
UART_send_buffer[length++] = 'm';
UART_send_buffer[length++] = 'e';
}
else
{
UART_send_buffer[length++] = 'D';
UART_send_buffer[length++] = 'a';
UART_send_buffer[length++] = 't';
UART_send_buffer[length++] = 'a';
UART_send_buffer[length++] = 'F';
UART_send_buffer[length++] = 'r';
UART_send_buffer[length++] = 'a';
UART_send_buffer[length++] = 'm';
UART_send_buffer[length++] = 'e';
}
UART_send_buffer[length++] = '\n';
UART_send_buffer[length++] = '\r';
if(CAN2_receive_buffer[Consumer][0] & (1<<2))
{
UART_send_buffer[length++] = 'e';
UART_send_buffer[length++] = 'x';
UART_send_buffer[length++] = 't';
UART_send_buffer[length++] = ' ';
UART_send_buffer[length++] = 'I';
UART_send_buffer[length++] = 'D';
UART_send_buffer[length++] = ':';
UART_send_buffer[length++] =
ascii[CAN2_receive_buffer[Consumer][0] >> 31];
UART_send_buffer[length++] =
ascii[(CAN2_receive_buffer[Consumer][0] >> 27)& 0x0000000f];
UART_send_buffer[length++] =
ascii[(CAN2_receive_buffer[Consumer][0] >> 23)& 0x0000000f];
UART_send_buffer[length++] =
ascii[(CAN2_receive_buffer[Consumer][0] >> 19)& 0x0000000f];
UART_send_buffer[length++] =
ascii[(CAN2_receive_buffer[Consumer][0] >> 15)& 0x0000000f];
UART_send_buffer[length++] =
ascii[(CAN2_receive_buffer[Consumer][0] >> 11)& 0x0000000f];
UART_send_buffer[length++] =
ascii[(CAN2_receive_buffer[Consumer][0] >> 7)& 0x0000000f];
UART_send_buffer[length++] =
ascii[(CAN2_receive_buffer[Consumer][0] >> 3)& 0x0000000f];
}
else
{
UART_send_buffer[length++] = 's';
UART_send_buffer[length++] = 't';
UART_send_buffer[length++] = 'd';
UART_send_buffer[length++] = ' ';
UART_send_buffer[length++] = 'I';
UART_send_buffer[length++] = 'D';
UART_send_buffer[length++] = ':';
UART_send_buffer[length++] =
ascii[CAN2_receive_buffer[Consumer][0] >> 29];
UART_send_buffer[length++] =
ascii[(CAN2_receive_buffer[Consumer][0] >> 25)& 0x0000000f];
UART_send_buffer[length++] =
ascii[(CAN2_receive_buffer[Consumer][0] >> 21)& 0x0000000f];
}
UART_send_buffer[length++] = '\n';
UART_send_buffer[length++] = '\r';
UART_send_buffer[length++] = 'D';
UART_send_buffer[length++] = 'a';
UART_send_buffer[length++] = 't';
UART_send_buffer[length++] = 'a';
UART_send_buffer[length++] = ':';
if(Data_length > 4)
{
for(i = 2*Data_length - 8; i > 0; i--)
UART_send_buffer[length++] =
ascii[(CAN2_receive_buffer[Consumer][3] >> ((i-1)*4))& 0x0000000f];
for(i = 8; i > 0; i--)
UART_send_buffer[length++] =
ascii[(CAN2_receive_buffer[Consumer][2] >> ((i-1)*4))& 0x0000000f];
}
else
{
for(i = 2*Data_length; i > 0; i--)
UART_send_buffer[length++] =
ascii[(CAN2_receive_buffer[Consumer][2] >> ((i-1)*4))& 0x0000000f];
}
UART_send_buffer[length++] = '\n';
UART_send_buffer[length++] = '\r';
}
else
break;
}
return length;
}
void Delay(uint32_t nTime)
{
Gb_TimingDelay = nTime;
while(Gb_TimingDelay != 0);
}
void SysTick_Handler(void)
{
if (Gb_TimingDelay != 0x00)
{
Gb_TimingDelay--;
}
}
|