第二节 带CAN控制器的C8051F040处理器
一、内部结构及引脚 模拟外设
- SAR ADC
12 位(C8051F040/1)
10 位(C8051F042/3/4/5/6/7)
±1LSB INL,保证无失码
可编程转换速率,最大 100ksps
13 个外部输入;单端或差分输入方式
软件可编程高电压差分放大器
可编程放大器增益:
16、
8、
4、
2、
1、0.5
数据相关窗口中断发生器
内建温度传感器
- 8 位 ADC(仅限于 C8051F040/1/2/3)
可编程转换速率,最大 500ksps
8 个外部输入(单端或差分)
可编程放大器增益:
4、
2、
1、0.5 外部振荡器:晶体、RC、C 或外部时钟
- 实时时钟方式(使用定时器
2、
3、4 或 PCA)
供电电压:2.7 ~ 3.6V
- 多种节电休眠和停机方式
100 脚 TQFP 和 64 脚 TQFP 封装
- 温度范围:-40°CID0 29-bit 标识符 (“Extended Frame”).ID28 - ID18 11-bit标识符(“Standard Frame”).Msk28-0:Identifier Mask 1:对应的标识符位参与验收滤波。 0:对应的标识符位不参与验收滤波。 Xtd: Extended Identifier 1: 29-bit (“扩展”) 标识符用于消息对象。 0: 11-bit (“标准”) 标识符用于消息对象。 MXtd:Mask Extended Identifier 1:扩展帧标识位(IDE) 参与验收滤波。 0:扩展帧标识位(IDE)不参与验收滤波。 Dir:Meage Direction 1:发送方向。 0:接收方向
MDir:Mask Meage Direction 1: (Dir) 位用于验收滤波。 0:(Dir) 位不用于验收滤波。 EoB:End of Buffer 1:在FIFO中唯一一个或者最后一个消息对象。 0:在FIFO中不是唯一一个或者最后一个消息对象。 NewDat:New Data 1:消息对象中有新数据。 0:消息对象中没有新数据。
MsgLst:eage Lost (only valid for Meage Objects with direction = receive) 1:CPU丢失数据。 0:CPU未丢失数据。
RxIE :Receive Interrupt Enable 1:接收中断允许位。 0:接收中断禁止位。
TxIE:Transmit Interrupt Enable 1:发送中断允许位。 0:发送中断禁止位。 IntPnd:Interrupt Pending 1:消息对象作为中断源。 0:消息对象不作为中断源。 RmtEn:Remote Enable 1:允许远程帧接收。 0:禁止远程帧接收。 TxRqst:Transmit Request 1:消息对象中的数据申请发送。 0:消息对象中没有待发送的数据。 DLC3-0:Data Length Code 0-8 Data Frame has 0-8 data bytes.9-15 Data Frame has 8 data bytes
(9)消息处理寄存器
①中断寄存器:按优先级处理。
IntId15-0 :中断标识号 0x0000 没有中断申请。
0x0001-0x0020 引起中断的消息对象的索引号。 0x0021-0x7FFF 未用。 0x8000 状态中断。 0x8001-0xFFFF 未用。 ②发送请求寄存器
6、CAN应用 (1)初始化
初始化CAN 控制器的一般步骤如下:
1) 将SFRPAGE 寄存器设置为CAN0_PAGE。 2) 将CAN0CN 寄存器中的INIT 和CCE 位设置为1。 3) 设置位定时寄存器和BRP 扩展寄存器中的时序参数。
4) 初始化每个消息对象或将其MsgVal 位设置为NOT VALID(无效)。 5) 将INIT 位清„0‟。
(2)数据在IFx与消息对象间的传输流程:
接收程序:
例程:
消息对象清0程序: void clear_msg_objects (void) { SFRPAGE = CAN0_PAGE;
//SFR设置为CAN寄存器页 CAN0ADR = IF1CMDMSK;
// 指向命令掩码寄存器1 CAN0DATL = 0xFF;
// 对IF消息对象设为写入 for (i=1;i
// 消息对象清0 CAN0DATL = i; } }
消息对象初始化为接收对象: void init_msg_object_RX (char MsgNum) { SFRPAGE = CAN0_PAGE; CAN0ADR = IF1CMDMSK; CAN0DAT = 0x00B8;
// 写入方式, 除ID MASK和数据位外 CAN0ADR = IF1ARB1;
// IF1ARB1=0 CAN0DAT = 0x0000; CAN0DAT = 0x8004;
// Arb2 设置:标准帧,接收 CAN0DAT = 0x0480;
// 禁止远程帧 CAN0ADR = IF1CMDRQST;
// 命令请求寄存器
CAN0DATL = MsgNum;
// 选择消息对象,初始化为写入 // 3-6 CAN时钟周期后 IF的内容移入消息对象 } 初始化消息对象为发送对象: void init_msg_object_TX (char MsgNum) { SFRPAGE = CAN0_PAGE; CAN0ADR = IF1CMDMSK; CAN0DAT = 0x00B2;
//写入方式, 除ID MASK外 CAN0ADR = IF1ARB1; CAN0DAT = 0x0000;
// 仲裁段1的标识符设为最高优先级 CAN0DAT = 0xA000;
// Arb2 设置:标准帧,写入 CAN0DAT = 0x0081;
// 消息控制: DLC = 1,禁止远程帧 CAN0ADR = IF1CMDRQST; CAN0DAT = MsgNum;
//选择消息对象,初始化为写入 //3-6 CAN时钟周期后 IF的内容移入消息对象 } CAN通信初始化 void start_CAN (void) { SFRPAGE = CAN0_PAGE; CAN0CN |= 0x41;
// CCE和INIT设置 CAN0ADR = BITREG ;
// 位定时寄存器设置 CAN0DAT = 0x2640; CAN0ADR = IF1CMDMSK; CAN0DAT = 0x0087;
// TX配置:数据写入CAN RAM // RX-IF2 的操作可以中断TX-IF1的操作 CAN0ADR = IF2CMDMSK; CAN0DATL = 0x1F;
// RX配置:从CAN RAM读取数据 // 清除NewDat和IntPnd CAN0CN |= 0x06;
// 允许IE、SIE CAN0CN &= ~0x41;
// 清除CCE 和INIT,准备CAN通信 } 发送程序:把数据55H发给消息\"MsgNum\"。 void transmit_turn (char MsgNum) { SFRPAGE = CAN0_PAGE;
// IF1 已经准备好发送 CAN0ADR = IF1CMDMSK; CAN0DAT = 0x0087;
// TX配置:数据写入CAN RAM // 置位TXrqst/NewDat,清除IntPnd CAN0ADR = IF1DATA1;
// 指向第一个数据字节 CAN0DATL = 0x55; CAN0ADR = IF1CMDRQST; CAN0DATL = MsgNum;
// 新数据发送给消息\"MsgNum\" } 接收程序:
void receive_data (char MsgNum) { char recive; SFRPAGE = CAN0_PAGE;
// IF2已经设置为接收 CAN0ADR = IF2CMDRQST; CAN0DATL = MsgNum;
// 新数据从消息 \"MsgNum\" 接收 CAN0ADR = IF2DATA1;
// 数据存储 recive = CAN0DATL; } 中断服务程序:
void ISRname (void) interrupt 19 { status = CAN0STA; if ((status&0x10) != 0) {
// RxOk =1,接收中断
CAN0STA = (CAN0STA&0xEF)|0x07;
// 复位RxOk, LEC设为未变 /*读取消息*/ receive_data (0x01);
// 只接收到一条消息 } if ((status&0x08) != 0) {
// TxOk =1,发送中断 CAN0STA = (CAN0STA&0xF7)|0x07;
// 复位TxOk,LEC设为未变 } if (((status&0x07) != 0)&&((status&0x07) != 7)) {
// 错误中断, LEC的值有变化 /* 错误处理 */ CAN0STA = CAN0STA|0x07;
// LEC设为未变 } }