总线型单片机普遍设置有并行地址总线、 数据总线、控制总线,这些引脚用以扩展并行外围器件都可通过串行口与单片机连接。
注:许多单片机已把所需要的外围器件及外设接口集成一片内,因此在许多情况下可以不要并行扩展总线,大大减省封装成本和芯片体积,这类单片机称为非总线型单片机。
单片机简介:
单片机=是一种集成电路芯片,是采用超大规模集成电路技术把具有数据处理能力的中央处理器CPU、随机存储器RAM、只读存储器ROM、多种I/O口和中断系统、定时器/计数器等功能(可能还包括显示驱动电路、脉宽调制电路、模拟多路转换器、A/D转换器等电路)集成到一块硅片上构成的一个小而完善的微型计算机系统,在工业控制领域广泛应用。从上世纪80年代,由当时的4位、8位单片机,发展到现在的300M的高速单片机。
首先,CAN通信需要有接口的,在有接收的基础上,再加一片CAN总线驱动芯片PCA82C250才行。这是要看你是什么单片机了,有的单片机带有CAN接口的,就像带有串口UART一样。
带有CAN接口的单片机,有专用的通信用寄存器来实现通信,与串口无关。
没有CAN接口的单片机,如51系列的,就需要加一片CAN扩展接收芯片,如SJA1000,通信时,是按外部扩展接口来实现的,当然了,用SJA1000也同样需要PCA82C250芯片的。
另外,在CAN通信时,具有很严格的通信协议的,必须按协议写程序才行的。并不像串口通信那么简单的。
主函数如下:uint8 systick_flag
// 主函数(程序入口)
int main(void)
{
uint8 systick_bak
jtagWait()//防止JTAG失效,重要!
clockInit() //时钟初始化:晶振,6MHz
board_initialize()//初始化
SysTickPeriodSet(100000UL)//设置SysTick计数器的周期值2ms
SysTickIntEnable()//使能SysTick中断
IntMasterEnable() //使能处理器中断
SysTickEnable() //使能SysTick计数器
serialInit()
CANConfigure()
for ()
{
if(systick_bak != systick_flag) // 2ms定时到
{
systick_bak = systick_flag
CANSend()
if(can_error_flag)
{
can_error_flag = 0
SysCtlDelay(15 * TheSysClock / 3000)
CANConfigure()
}
}
}
}
//
void SysTick_ISR(void)
{
// 硬件会自动清除SysTick中断状态
systick_flag += 1
}
#define _CAN_DEAL_C_
#include "config.h"
#include "can_deal.h"
#include "serial_com.h"
tCANMsgObject g_MsgObjectRx // CAN接收报文对象设置
tCANMsgObject g_MsgObjectTx // CAN发送报文对象设置
tCANBitClkParms CANBitClkSettings[] =
{
/*50MHz*/
{5, 4, 3, 5}, /* CANBAUD_1M */
{5, 4, 3, 10}, /* CANBAUD_500K */
{5, 4, 3, 20}, /* CANBAUD_250K */
{5, 4, 3, 40}, /* CANBAUD_125K */
{5, 4, 3, 50}, /* CANBAUD_100k */
{11, 8, 4, 50}, /* CANBAUD_50k */
{11, 8, 4, 100}, /* CANBAUD_25k */
{11, 8, 4, 125}, /* CANBAUD_20k */
{11, 8, 4, 250}, /* CANBAUD_10k */
{11, 8, 4, 500}, /* CANBAUD_5k */
{11, 8, 4, 1000},/* CANBAUD_2k5 */
}
uint8 can_recebuf[8]
uint8 can_sendbuf[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x51,0x0e}
uint8 cop_frame_addr
uint16 SendID,ReceID
/*************************************************
函数名称: CANConfigure
简要描述:配置CAN0的外设
调用清单:
被调用清单:
输入:
输出:
返回:
其它:
修改日志:
*************************************************/
void CANConfigure(void)
{
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA) //使能GPIOD系统外设
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB)
SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0) //使能CAN控制器系统外设
GPIOPinConfigure(GPIO_PA6_CAN0RX)
GPIOPinConfigure(GPIO_PB5_CAN0TX)
GPIOPinTypeCAN(GPIO_PORTA_BASE, GPIO_PIN_6 )
GPIOPinTypeCAN(GPIO_PORTB_BASE, GPIO_PIN_5 )
CANInit(CAN0_BASE) //初始化CAN节点
CANBitTimingSet(CAN0_BASE,
(tCANBitClkParms *)&CANBitClkSettings[CANBAUD_50k]) //对CAN控制器位时序进行配置
CANEnable(CAN0_BASE) //使能CAN控制器
CANIntEnable(CAN0_BASE, CAN_INT_MASTER | CAN_INT_STATUS | CAN_INT_ERROR) //使能CAN控制器中断源
IntEnable(INT_CAN0) //使能CAN控制器中断(to CPU)
IntMasterEnable()//使能中断总开关
cop_frame_addr = 0
}
/*************************************************
函数名称: CANRece
简要描述:配置接收数据帧
调用清单:
被调用清单:
输入:
输出:无
返回:
其它:
修改日志:
*************************************************/
void CANRece(void)
{
g_MsgObjectRx.ulMsgID = 0x110 //报文滤波ID
g_MsgObjectRx.ulMsgIDMask = 0x00//报文ID掩码
g_MsgObjectRx.ulFlags = MSG_OBJ_RX_INT_ENABLE
| MSG_OBJ_EXTENDED_ID | MSG_OBJ_USE_ID_FILTER |MSG_OBJ_DATA_LOST //由tCANObjFlags列举的配置参数:使能或已使能接收中断 g_MsgObjectRx.pucMsgData = sizeof(can_recebuf) //指向数据存储空间
g_MsgObjectRx.ulMsgLen= 8//设置数据域长度
CANMessageSet(CAN0_BASE, 3, &g_MsgObjectRx, MSG_OBJ_TYPE_RX) //配置数据帧"接收报文对象"
}
/*************************************************
函数名称: CANSend
简要描述:配置发送数据
调用清单:
被调用清单:
输入:
输出:无
返回:
其它:
修改日志:
*************************************************/
void CANSend(void)
{
g_MsgObjectTx.ulMsgID = SendID//取得报文标识符
g_MsgObjectTx.ulMsgIDMask = 0x00
g_MsgObjectTx.ulFlags = MSG_OBJ_TX_INT_ENABLE //标记发送中断使能
g_MsgObjectTx.ulMsgLen = sizeof(can_sendbuf) //标记数据域长度
CAN_ReceDeal()
if(cop_frame_addr == 0)
{
cop_frame_addr = 1
can_sendbuf[6] = 0x52 //参考原始
can_sendbuf[7] = crc_8(can_sendbuf,7)
g_MsgObjectTx.pucMsgData = can_sendbuf//传递数据存放指针
CANRetrySet(CAN0_BASE, 1) //启动发送失败重发
CANMessageSet(CAN0_BASE, 1, &g_MsgObjectTx, MSG_OBJ_TYPE_TX) //配置1号报文对象为发送对象
}
else
{
cop_frame_addr = 0
can_sendbuf[6] = 0x51 //参考原始
can_sendbuf[7] = crc_8(can_sendbuf,7)
g_MsgObjectTx.pucMsgData = can_sendbuf//传递数据存放指针
CANRetrySet(CAN0_BASE, 1) //启动发送失败重发
CANMessageSet(CAN0_BASE, 2, &g_MsgObjectTx, MSG_OBJ_TYPE_TX) //配置2号报文对象为发送对象
}
}
/*************************************************
函数名称: CANIntHandler
简要描述: CAN中断处理
调用清单:
被调用清单:
输入:
输出:无
返回:
其它:
修改日志:
*************************************************/
void CANIntHandler(void)
{
unsigned long ulStatus
ulStatus = CANIntStatus(CAN0_BASE, CAN_INT_STS_CAUSE)//读取CANMSGnINT寄存器的值
if(ulStatus == CAN_INT_INTID_STATUS) // Status Interrupt 状态中断
{
CANStatusGet(CAN0_BASE, CAN_STS_CONTROL)
}
else if(ulStatus == 1||ulStatus == 2)
{
CANIntClear(CAN0_BASE, ulStatus)
CANRece()
}
else if(ulStatus == 3)
{
g_MsgObjectRx.pucMsgData = can_recebuf
CANMessageGet(CAN0_BASE, 3, &g_MsgObjectRx, 0)
CANIntClear(CAN0_BASE, 3)
CANSend()
}
else
{
can_error_flag = 1
CANIntClear(CAN0_BASE, ulStatus)
}
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)