/**********************************************************************************
* 工程名 :泥人MCP2515模块-标准帧例程
* 描述 :电脑通过"串口调试助手"软件给单片机串口1发送数据,串口1接收到数据后
* 再通过CAN模块发送到另一个CAN模块;同时CAN模块接收到的CAN数据通过单
* 片机串口1发送到电脑。
* 实验平台:NiRen_STC/IAP15核心板(或用户STC15单片机开发板) + NiRen_MCP2515 CAN模块
* 硬件连接: P2^3 -> MCP2515_SCK SPI时钟引脚
* P2^2 -> MCP2515_MOSI SPI主机输出从机输入引脚
* P2^1 -> MCP2515_MISO SPI主机输入从机输出引脚
* P2^0 -> MCP2515_CS SPI片选引脚
* P3^3 -> MCP2515_INT MCP2515中断引脚
* 作者 :泥人通信模块开发团队
* 博客 :http://nirenelec.blog.163.com
* 淘宝 :http://nirenelec.taobao.com
**********************************************************************************/
/*********************************************************************************/
/*注意:本例程是基于STC12系列新型增强型51单片机编写,由于不同系列51单片机一些外设*/
/*功能配置存在差异,请亲们在使用时对应进行修改。*/
/*********************************************************************************/
#include "STC12C5Axx.h"
#include "MCP2515.H"
#define FOSC 11059200L //系统频率
#define T1MS (65536-FOSC/1000) //定时器工作在1T模式下定时1ms的计数器值(写入THx、TLx的值)
#define BAUD 9600 //串口1波特率
#define UART1_Rx_Buff_LEN 100 //串口1数据缓冲区数据长度
bit busy=0; //串口1发送数据忙标志位
unsigned char UART1_Rx_Buffer[UART1_Rx_Buff_LEN]; //串口1接收保存缓冲区
unsigned char Uart1_Delay=0; //串口1接收数据帧延时(ms),延时时间到当1帧数据接收完成
unsigned char Uart1_Write_Count=0; //写串口1缓冲区指针
unsigned char Uart1_Read_Count=0; //读串口1缓冲区指针
unsigned char Uart1_Finish=0; //当前一帧数据接收完成标志
unsigned char CAN_Flag=0; //CAN接收到数据标志
unsigned char CAN_R_Buffer[8]; //CAN接收数据保存缓冲区
/*******************************************************************************
* 函数名 : Timer0_Init
* 描述 : 定时器0初始化配置
* 输入 : 无
* 输出 : 无
* 返回值 : 无
* 说明 : 无
*******************************************************************************/
void Timer0_Init(void)
{
AUXR |= 0x80; //定时器0为1T模式
TMOD &= 0xF0;
TMOD |= 0x01; //设置定时器为模式0(16位自动重装载)
TL0 = T1MS; //初始化计时值
TH0 = T1MS >> 8;
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
EA = 1; //使能总中断
}
/*******************************************************************************
* 函数名 : Timer0_ISR
* 描述 : 定时器0中断服务函数
* 输入 : 无
* 输出 : 无
* 返回值 : 无
* 说明 : 本程序用于检测1帧串口数据接收完成
*******************************************************************************/
void Timer0_ISR() interrupt 1 using 1
{
if(Uart1_Delay>0)
{
Uart1_Delay--;
if(Uart1_Delay==0)
{
//延时时间到再没有接收到新的串口数据,表示1帧数据接收完成
if(Uart1_Write_Count != Uart1_Read_Count) Uart1_Finish=1;
}
}
TL0 = T1MS; //初始化计时值
TH0 = T1MS >> 8;
}
/*******************************************************************************
* 函数名 : Exint1_Init
* 描述 : 外部中断1初始化函数
* 输入 : 无
* 输出 : 无
* 返回值 : 无
* 说明 : 无
*******************************************************************************/
void Exint1_Init(void)
{
PX1=1; //设置外部中断1的中断优先级为高优先级
IT1 = 1; //设置INT1的中断类型 (1:仅下降沿 0:上升沿和下降沿)
EX1 = 1; //使能INT1中断
EA = 1; //使能总中断
}
/*******************************************************************************
* 函数名 : Exint1_ISR
* 描述 : 外部中断1中断服务函数
* 输入 : 无
* 输出 : 无
* 返回值 : 无
* 说明 : 用于检测MCP2515中断引脚的中断信号
*******************************************************************************/
void Exint1_ISR(void) interrupt 2 using 1
{
CAN_Flag=1;//CAN接收到数据标志
}
/*******************************************************************************
* 函数名 : UART1_Init_Config
* 描述 : UART1初始化配置
* 输入 : 无
* 输出 : 无
* 返回值 : 无
* 说明 : 无
*******************************************************************************/
void UART1_Init_Config(void)
{
SCON = 0x50; //8位UART,可变波特率,允许串行接收
TMOD &= 0x0F;
TMOD |= 0x20; //定时器1为8位自动重载模式
TH1 = TL1 = -(FOSC/12/32/BAUD); //设置波特率重装值
TR1 = 1; //启动定时器1计数
ES = 1; //使能串口中断
EA = 1; //使能总中断
}
/*******************************************************************************
* 函数名 : UART1_Buffer_PntAdd
* 描述 : 读、写串口1缓冲区指针加1
* 输入 : *pnt(指向串口1读、写串口1缓冲区指针)
* 输出 : 无
* 返回值 : 无
* 说明 : 无
*******************************************************************************/
void UART1_Buffer_PntAdd(unsigned char *pnt)
{
*pnt+=1;
if(*pnt >= UART1_Rx_Buff_LEN) *pnt=0;
}
/*******************************************************************************
* 函数名 : UART1_ISR
* 描述 : UART1中断服务函数
* 输入 : 无
* 输出 : 无
* 返回值 : 无
* 说明 : 无
*******************************************************************************/
void UART1_ISR(void) interrupt 4 using 1
{
unsigned char ch;
//接收数据
if(RI)
{
RI = 0;//清除RI位
ch=SBUF;
UART1_Rx_Buffer[Uart1_Write_Count]=ch; //将接收到的数据写入缓冲区
UART1_Buffer_PntAdd(&Uart1_Write_Count);//写串口1缓冲区指针加1
if(Uart1_Write_Count == Uart1_Read_Count)//如果读、写缓冲区指针重叠,则读指针加1,这时将丢失1个字节数据
{
UART1_Buffer_PntAdd(&Uart1_Read_Count);//读串口1缓冲区指针加1
}
Uart1_Delay = 20;//串口1接收数据帧延时(ms),延时时间到当1帧数据接收完成
}
//发送数据
if (TI)
{
TI = 0; //清除TI位
busy = 0; //清忙标志(1忙,0空闲)
}
}
/*******************************************************************************
* 函数名 : UART1_SendData
* 描述 : UART1发送一个字节
* 输入 : dat:待发送数据
* 输出 : 无
* 返回值 : 无
* 说明 : 无
*******************************************************************************/
void UART1_SendData(unsigned char dat)
{
while (busy); //等待前面的数据发送完成
busy = 1; //串口1发送数据忙标志位(1忙,0空闲)
SBUF = dat; //写数据到UART数据寄存器
}
/*******************************************************************************
* 函数名 : UART1_SendBuffer
* 描述 : UART1发送一个缓冲区数据
* 输入 : *buff:待发送缓冲区首地址,len:待发送数据长度
* 输出 : 无
* 返回值 : 无
* 说明 : 无
*******************************************************************************/
void UART1_SendBuffer(unsigned char *buff,unsigned int len)
{
unsigned int i=0;
if(len<=0) return;
do
{
UART1_SendData(buff[i++]);//发送当前字符
}while(i<len);
}
/*******************************************************************************
* 函数名 : CAN_Send_Dispose
* 描述 : CAN发送串口1接收到的数据处理函数
* 输入 : 无
* 输出 : 无
* 返回值 : 无
* 说明 : 无
*******************************************************************************/
void CAN_Send_Dispose(void)
{
unsigned char i=0,len=0,write=0,buff[8];
write = Uart1_Write_Count;
if(Uart1_Write_Count<Uart1_Read_Count) write+=UART1_Rx_Buff_LEN;
if((write-Uart1_Read_Count) >= 8)//如果串口1接收缓冲区中未读数据大于8个字节,则通过CAN总线发送8个字节数据(CAN发送一帧报文最大8个字节)
{
len = 8;
}
else if(Uart1_Finish == 1)//如果串口1接收缓冲区中未读数据小于8个字节,且再也没接收到串口的数据,则CAN发送剩余的数据
{
len = write-Uart1_Read_Count;
Uart1_Finish=0;//当前一帧数据接收完成标志
}
else return;//如果串口1接收缓冲区中未读数据小于8个字节,且还在接收串口的数据则CAN先不发数据,等够8个字节了再发
for(i=0;i<len;i++)
{
评论1