增城网站建设价格,深圳头条新闻,中国有没有做的好的网站,wordpress中文广告插件下载断断续续#xff0c;零星学习这个
首先#xff0c;在SJA1000STC89C52硬件电路上#xff0c;来回折腾近好久
本来是想着开发板TJA1050模块#xff0c;用杜邦线链接#xff0c;先实现自收发。
结果死活不会自收发#xff0c;没办法#xff0c;只能去掏了2块CAN开发板. …断断续续零星学习这个
首先在SJA1000STC89C52硬件电路上来回折腾近好久
本来是想着开发板TJA1050模块用杜邦线链接先实现自收发。
结果死活不会自收发没办法只能去掏了2块CAN开发板.
总算有点进度记录如下
1-期间重新拜读了吴坚鸿大神的源码并且使用了相关按键和数码管部分的源码
出现了一直很神奇的现象不知道缘由待高手路过指点一下
我先说下现象情况 原来单片机开发板程序 显示的数字相同 改了之后显示收的数字比发大了1。 一步步的替换也试过按键部分替换后正常就是替换到数码管部分
按第一下后发的数字是1 收的数字还是0再按一后发的数字是2收的数字成了1
原先是按一下后发的数字是1收的数字也是1.
首先是源程序
/*************************************************
*功能: CEPARK CAN开发板-CAN自收发实验
*说明数码管从右到左分别是1~4位。
* 数码管1、2位显示发送的数据3、4位显示接收到的数据。
* 每按一次中断按键发送数据值增一。
*芯片STC89C52RC
*跳线无****************************************************/
#include reg52.h
#include sjapelican.h
#include config.h//INT0按键为计数按键
void INT0_Data(void) interrupt 0
{EA 0;Txd_data; //存储计数结果并为待发送的数据Peli_TXD();EA 1;
}
//接收数据函数在中断服务程序中调用
void Peli_RXD(void) interrupt 2
{uint8 data Status;EA 0;//关CPU中断Status SJA_IR;if(Status RI_BIT){//IR.0 1 接收中断RX_buffer[0] SJA_RBSR0;RX_buffer[1] SJA_RBSR1;RX_buffer[2] SJA_RBSR2;RX_buffer[3] SJA_RBSR3;RX_buffer[4] SJA_RBSR4;RX_buffer[5] SJA_RBSR5;RX_buffer[6] SJA_RBSR6;RX_buffer[7] SJA_RBSR7;RX_buffer[8] SJA_RBSR8;RX_buffer[9] SJA_RBSR9;RX_buffer[10] SJA_RBSR10;RX_buffer[11] SJA_RBSR11;RX_buffer[12] SJA_RBSR12;SJA_CMR RRB_BIT;Status SJA_ALC;//释放仲裁随时捕捉寄存器Status SJA_ECC;//释放错误代码捕捉寄存器}SJA_IER RIE_BIT;// .01--接收中断使能Rxd_data RX_buffer[5];EA 1;//打开CPU中断
}
//CPU初始化
void MCU_Init(void)
{SJA_RST 0;//SJA1000复位有效mDelay(10); //延时SJA_RST 1;//CAN总线复位管脚,复位无效SJA_CS 0;//CAN总线片选有效EX1 1;//外部中断1使能CAN总线接收中断IT1 0;//CAN总线接收中断低电平触发IT0 1;//外部中断0负边沿触发EX0 1;//打开外部中断0EA 1; //打开总中断
}
//主函数
void main(void)
{MCU_Init();Peli_Init();// mDelay(1);while(1) LED_Disp_Seg7(); //数码管显示函数
}//SJA1000 的初始化
void Peli_Init(void)
{uint8 bdata Status;do{// .01---reset MODRe,进入复位模式以便设置相应的寄存器//防止未进入复位模式重复写入SJA_MOD RM_BIT |AFM_BIT;Status SJA_MOD ;}while(!(Status RM_BIT));SJA_CDR CANMode_BIT|CLKOff_BIT;// CDR.31--时钟关闭, .70---basic CAN, .71---Peli CAN 时钟分频SJA_BTR0 0x03;SJA_BTR1 0x1c;//16M晶振波特率125KbpsSJA_IER RIE_BIT;// .01--接收中断使能 .10--关闭发送中断使能SJA_OCR NormalMode|Tx0PullDn|OCPOL1_BIT|Tx1PullUp;// 配置输出控制寄存器SJA_CMR RRB_BIT;//释放接收缓冲器SJA_ACR0 0x11;SJA_ACR1 0x22;SJA_ACR2 0x33;SJA_ACR3 0x44;//初始化标示码 验收代码寄存器SJA_AMR0 0xff;SJA_AMR1 0xff;SJA_AMR2 0xff;SJA_AMR3 0xff;//初始化掩码 验收屏蔽寄存器do //确保进入自接收模式{ SJA_MOD STM_BIT;Status SJA_MOD;}while( !(Status STM_BIT) );}//发送数据函数
void Peli_TXD( void )
{uint8 data Status;
//初始化标示码头信息TX_buffer[0] 0x88;//.70扩展帧.60数据帧; .31数据长度TX_buffer[1] 0x01;//本节点地址TX_buffer[2] 0x02;//TX_buffer[3] 0x03;//TX_buffer[4] 0x04;////初始化发送数据单元TX_buffer[5] Txd_data;TX_buffer[6] 0x22;TX_buffer[7] 0x33;TX_buffer[8] 0x44;//TX_buffer[9] 0x55;//TX_buffer[10] 0x66;//TX_buffer[11] 0x77;//TX_buffer[12] 0x88;//do{Status SJA_SR;LED_RED 0;}while( Status RS_BIT); //SR.41 正在接收等待do{Status SJA_SR;LED_RED 0;}while(!(Status TCS_BIT)); //SR.30,发送请求未处理完等待do{Status SJA_SR;LED_RED 0;}while(!(Status TBS_BIT)); //SR.20,发送缓冲器被锁。等待LED_RED !LED_RED;LED_GER !LED_GER;SJA_TBSR0 TX_buffer[0];SJA_TBSR1 TX_buffer[1];SJA_TBSR2 TX_buffer[2];SJA_TBSR3 TX_buffer[3];SJA_TBSR4 TX_buffer[4];SJA_TBSR5 TX_buffer[5];SJA_TBSR6 TX_buffer[6];SJA_TBSR7 TX_buffer[7];SJA_TBSR8 TX_buffer[8];SJA_TBSR9 TX_buffer[9];SJA_TBSR10 TX_buffer[10];SJA_TBSR11 TX_buffer[11];SJA_TBSR12 TX_buffer[12];SJA_CMR SRR_BIT;//置位自发送接收请求
}
//延时函数
void mDelay(uint16 mtime)
{for(; mtime 0; mtime--){uint8 j 244;while(--j);}
}
//数码管显示函数
void LED_Disp_Seg7()
{LedCtrl LedCtrl | 0xf0;DisBuff[0] Txd_data%10;//取个位数DisBuff[1] Txd_data%100/10; //取十位数DisBuff[2] Rxd_data%10; //百位数DisBuff[3] Rxd_data%100/10; //千位数LedPort LED_Disp[DisBuff[0]];LedCtrl LedCtrl 0x7f;mDelay(5);LedCtrl LedCtrl | 0xf0;LedPort LED_Disp[DisBuff[1]];LedCtrl LedCtrl 0xbf;mDelay(5);LedCtrl LedCtrl | 0xf0;LedPort LED_Disp[DisBuff[2]];LedCtrl LedCtrl 0xdf;mDelay(5);LedCtrl LedCtrl | 0xf0;LedPort LED_Disp[DisBuff[3]];LedCtrl LedCtrl 0xef;mDelay(5);LedCtrl LedCtrl | 0xf0;
}
#ifndef __CONFIG_H__
#define __CONFIG_H__#define Fclk 11059200UL /*使用11.0592M晶体*/
#define BAUD 9600UL /*波特率定义为9600*/#define uint8 unsigned char
#define uint16 unsigned short int
#define uint32 unsigned long int
#define int8 signed char
#define int16 signed short int
#define int32 signed long int
#define uint64 unsigned long long int
#define int64 signed long long int#endif
#ifndef __SJAPELICAN_H__
#define __SJAPELICAN_H__
#include absacc.h
#include config.h//数码管段码显示0~f,不亮
uint8 code LED_Disp[]
{0xC0,//00xF9,//10xA4,//20xB0,//30x99,//40x92,//50x82,//60xF8,//70x80,//80x90,//90x88,//10-a0x83,//11-b0xC6,//12-c0xA1,//13-d0x86,//14-e0x8E //15-f
};//sfr LedPort 0x80; //段选段P0
//sfr LedCtrl 0xa0; //位选段P2#define LedPort P0 //段选段P0 --- 要显示的数字
#define LedCtrl P2 //段选段P2 --- 选择那个数码管uint8 DisBuff[4];#define FrameNum 13//一帧字节数uint8 RX_buffer[FrameNum]; //接收的数据
uint8 TX_buffer[FrameNum]; //接收的数据
uint8 Txd_data 0;//CAN总线要发送的数据也是要在数码管1-2位置显示的数据
uint8 Rxd_data 0;//CAN总线要接收的数据也是要在数码管3-4位置显示的数据sbit SJA_RST P2^3;//SJA1000复位管脚
sbit SJA_CS P2^0;//SJA1000片选管脚sbit LED_REDP1^0;
sbit LED_GERP1^1; void MCU_Init(void); //CPU初始化
void Peli_Init(void); // 初始化CAN总线芯片
void Peli_TXD(void);//CAN发送子函数
void mDelay(uint16 mtime);//延时子函数
void LED_Disp_Seg7();//显示子函数#define SJA_BASE_ADR 0xfe00 //寄存器地址的基址//SJA1000寄存器地址定义作用在Peli模式扩展帧方式
/**********************
模式控制寄存器及其位定义
************************/
#define SJA_MOD XBYTE[SJA_BASE_ADR 0x00]#define RM_BIT 0x01 //复位模式请求位
#define LOM_BIT 0x02 //只听模式位
#define STM_BIT 0x04 //自检模式位
#define AFM_BIT 0x08 //验收滤波器模式位
#define SM_BIT 0x10 //睡眠模式位/**********************
命令寄存器及其位定义
************************/
#define SJA_CMR XBYTE[SJA_BASE_ADR 0x01]
#define TR_BIT 0x01 //发送请求位
#define AT_BIT 0x02 //中止发送位
#define RRB_BIT 0x04 //释放接收缓冲器位
#define CDO_BIT 0x08 //清除数据溢出位
#define SRR_BIT 0x10 //自身接收请求位/**********************
状态寄存器及其位定义
************************/
#define SJA_SR XBYTE[SJA_BASE_ADR 0x02]
#define RBS_BIT 0x01 //接收缓冲器状态位
#define DOS_BIT 0x02 //数据溢出状态位
#define TBS_BIT 0x04 //发送缓冲器状态位
#define TCS_BIT 0x08 //发送完成状态位
#define RS_BIT 0x10 //接收状态位
#define TS_BIT 0x20 //发送状态位
#define ES_BIT 0x40 //错误状态位
#define BS_BIT 0x80 //总线状态位/**********************
中断寄存器及其位定义
************************/
#define SJA_IR XBYTE[SJA_BASE_ADR 0x03]
#define RI_BIT 0x01 //接收中断位
#define TI_BIT 0x02 //发送中断位
#define EI_BIT 0x04 //错误警告中断位
#define DOI_BIT 0x08 //数据溢出中断位
#define WUI_BIT 0x10 //唤醒中断位
#define EPI_BIT 0x20 //错误消极中断位
#define ALI_BIT 0x40 //仲裁丢失中断位
#define BEI_BIT 0x80 //总线错误中断位/**********************
中断使能寄存器及其位定义
************************/
#define SJA_IER XBYTE[SJA_BASE_ADR 0x04]
#define RIE_BIT 0x01 //接收中断使能位
#define TIE_BIT 0x02 //发送中断使能位
#define EIE_BIT 0x04 //错误警告中断使能位
#define DOIE_BIT 0x08 //数据溢出中断使能位
#define WUIE_BIT 0x10 //唤醒中断使能位
#define EPIE_BIT 0x20 //错误消极中断使能位
#define ALIE_BIT 0x40 //仲裁丢失中断使能位
#define BEIE_BIT 0x80 //总线错误中断使能位#define SJA_BTR0 XBYTE[SJA_BASE_ADR 0x06] //总线定时器0寄存器
#define SJA_BTR1 XBYTE[SJA_BASE_ADR 0x07] //总线定时器1寄存器
#define SAM_BIT 0x80 //采样模式位0总线被采样1次1 总线被采样3次/**********************
输出控制寄存器及其位定义
************************/
#define SJA_OCR XBYTE[SJA_BASE_ADR 0x08]/*OCMODE1 OCMODE0 */
#define BiPhaseMode 0x00 //双相输出模式
#define NormalMode 0x02 //正常输出模式
#define ClkOutMode (0x01|0x02) //时钟输出模式/*TX1 的输出管脚配置*/
#define OCPOL1_BIT 0x20 //输出极性控制位
#define Tx1Float 0x00 //配置为悬空
#define Tx1PullDn 0x40 //配置为下拉
#define Tx1PullUp 0x80 //配置为上拉
#define Tx1PshPull (0x40|0x80) //配置为推挽/*TX0 的输出管脚配置*/
#define OCPOL0_BIT 0x04 //输出极性控制位
#define Tx0Float 0x00 //配置为悬空
#define Tx0PullDn 0x08 //配置为下拉
#define Tx0PullUp 0x10 //配置为上拉
#define Tx0PshPull (0x10|0x08) //配置为推挽#define SJA_TEST XBYTE[SJA_BASE_ADR 0x09] //测试寄存器/********************************* #define SJA_10 XBYTE[SJA_BASE_ADR 0x0a] 寄存器功能保留********************************//**********************
其他寄存器及其位定义
************************/
#define SJA_ALC XBYTE[SJA_BASE_ADR 0x0b] //仲裁丢失捕捉寄存器
#define SJA_ECC XBYTE[SJA_BASE_ADR 0x0c] //错误捕捉寄存器
#define SJA_EWLR XBYTE[SJA_BASE_ADR 0x0d] //错误报警限制寄存器
#define SJA_RXERR XBYTE[SJA_BASE_ADR 0x0e] //RX 错误计数器寄存器
#define SJA_TXERR XBYTE[SJA_BASE_ADR 0x0f] //TX 错误计数器寄存器/**********************
验收滤波器寄存器及其位定义
************************/
#define SJA_ACR0 XBYTE[SJA_BASE_ADR 0x10] //验收代码0寄存器
#define SJA_ACR1 XBYTE[SJA_BASE_ADR 0x11] //验收代码1寄存器
#define SJA_ACR2 XBYTE[SJA_BASE_ADR 0x12] //验收代码2寄存器
#define SJA_ACR3 XBYTE[SJA_BASE_ADR 0x13] //验收代码3寄存器#define SJA_AMR0 XBYTE[SJA_BASE_ADR 0x14] //验收屏蔽0寄存器
#define SJA_AMR1 XBYTE[SJA_BASE_ADR 0x15] //验收屏蔽1寄存器
#define SJA_AMR2 XBYTE[SJA_BASE_ADR 0x16] //验收屏蔽2寄存器
#define SJA_AMR3 XBYTE[SJA_BASE_ADR 0x17] //验收屏蔽3寄存器/**********************
TX缓冲器地址定义
************************/
#define SJA_TBSR0 XBYTE[SJA_BASE_ADR 0x10]
#define SJA_TBSR1 XBYTE[SJA_BASE_ADR 0x11]
#define SJA_TBSR2 XBYTE[SJA_BASE_ADR 0x12]
#define SJA_TBSR3 XBYTE[SJA_BASE_ADR 0x13]
#define SJA_TBSR4 XBYTE[SJA_BASE_ADR 0x14]
#define SJA_TBSR5 XBYTE[SJA_BASE_ADR 0x15]
#define SJA_TBSR6 XBYTE[SJA_BASE_ADR 0x16]
#define SJA_TBSR7 XBYTE[SJA_BASE_ADR 0x17]
#define SJA_TBSR8 XBYTE[SJA_BASE_ADR 0x18]
#define SJA_TBSR9 XBYTE[SJA_BASE_ADR 0x19]
#define SJA_TBSR10 XBYTE[SJA_BASE_ADR 0x1a]
#define SJA_TBSR11 XBYTE[SJA_BASE_ADR 0x1b]
#define SJA_TBSR12 XBYTE[SJA_BASE_ADR 0x1c]/**********************
RX缓冲器地址定义
************************/
#define SJA_RBSR0 XBYTE[SJA_BASE_ADR 0x10]
#define SJA_RBSR1 XBYTE[SJA_BASE_ADR 0x11]
#define SJA_RBSR2 XBYTE[SJA_BASE_ADR 0x12]
#define SJA_RBSR3 XBYTE[SJA_BASE_ADR 0x13]
#define SJA_RBSR4 XBYTE[SJA_BASE_ADR 0x14]
#define SJA_RBSR5 XBYTE[SJA_BASE_ADR 0x15]
#define SJA_RBSR6 XBYTE[SJA_BASE_ADR 0x16]
#define SJA_RBSR7 XBYTE[SJA_BASE_ADR 0x17]
#define SJA_RBSR8 XBYTE[SJA_BASE_ADR 0x18]
#define SJA_RBSR9 XBYTE[SJA_BASE_ADR 0x19]
#define SJA_RBSR10 XBYTE[SJA_BASE_ADR 0x1a]
#define SJA_RBSR11 XBYTE[SJA_BASE_ADR 0x1b]
#define SJA_RBSR12 XBYTE[SJA_BASE_ADR 0x1c]#define SJA_RMC XBYTE[SJA_BASE_ADR 0x1d] //RX 信息计数器 寄存器
#define SJA_RBSA XBYTE[SJA_BASE_ADR 0x1e] //RX 缓冲区起始地址 寄存器/**********************
时钟分频寄存器地址定义
************************/
#define SJA_CDR XBYTE[SJA_BASE_ADR 0x1f] //时钟分频 寄存器
#define CLKOff_BIT 0x08 //时钟关闭位时钟输出管脚控制位
#define RXINTEN_BIT 0x20 //用于接收中断的管脚TX1
#define CBP_BIT 0x40 //CAN 比较器旁路控制位
#define CANMode_BIT 0x80 //CAN 模式控制位#endif
然后是我移植修改的代码我把两个.H 都放在一起了
/*********************************文件注释******************************** project(项目 xxx* file(文件名) main.c * Description(说明) 实现功能一共有4个窗口。每个窗口显示一个参数。第8,7,6,5位数码管显示当前窗口P-1代表第1个窗口P-2代表第2个窗口P-3代表第3个窗口P-4代表第1个窗口。第4,3,2,1位数码管显示当前窗口被设置的参数。范围是从0到9999。有三个按键。一个是加按键按下此按键会依次增加当前窗口的参数。一个是减按键按下此按键会依次减少当前窗口的参数。一个是切换窗口按键按下此按键会依次循环切换不同的窗口。并且要求被设置的数据不显示为0的高位。比如参数是12时不能显示“0012”只能第4,3位不显示第2,1位显示“12”。功能: CEPARK CAN开发板-CAN自收发实验*说明数码管从右到左分别是1~4位。* 数码管1、2位显示发送的数据3、4位显示接收到的数据。* 每按一次中断按键发送数据值增一。
*芯片STC89C52RC* author(作者) qw* version(版本号) V1.0* date(日期) 2023-1-28* Company(公司)* History(历史修改记录)*跳线无*版本CEPARK CAN总线开发板v3.0author time version desc
*******************************************************************************/
/*
开场白
上一节在第4,3,2,1位显示设置的参数时还有一点小瑕疵。
比如设置参数等于56时实际显示的是“0056”也就是高位为0的如果不显示效果才会更好。
这一节要教会大家两个知识点
第一个在上一节Smg_Service()函数里略作修改把高位为0的去掉不显示。
第二个加深熟悉鸿哥首次提出的“一二级菜单显示理论”
凡是人机界面显示不管是数码管还是液晶屏都可以把显示的内容分成不同的窗口来显示
每个显示的窗口中又可以分成不同的局部显示。
其中窗口就是一级菜单用ucWd变量表示。局部就是二级菜单用ucPart来表示。
不同的窗口会有不同的更新显示变量ucWdXUpdate来对应表示整屏全部更新显示。
不同的局部也会有不同的更新显示变量ucWdXPartYUpdate来对应表示局部更新显示。*/
#include reg52.h
#include absacc.h/**********************字符符号类型缩写
************************/
#define u8 unsigned char
#define u16 unsigned short int
#define u32 unsigned long int
#define s8 signed char
#define s16 signed short int
#define s32 signed long int
#define u64 unsigned long long int
#define s64 signed long long int/**********************
SJA1000 寄存器配置
************************//*CAN总线SJA1000寄存器地址定义用的是PeliCAN模式扩展帧EFF模式*/
//为什么地址上0xFE00
//FE是因为我们有16位的地址线。P0口是低8位地址P2口是高8位地址。
//而P20是接的CS端一定要是为0,所以地址是FE.
//定义SJA1000的基址
//#define SJA_BaseAdr 0X7F00 //决定CS接到P2口的那个管脚这样定义就是P2.7
//#define SJA_BaseAdr 0XFE00 //决定CS接到P2口的那个管脚这样定义就是P2.0#define SJA_BASE_ADR 0xfe00 //寄存器地址的基址//SJA1000寄存器地址定义作用在Peli模式扩展帧方式
/**********************
模式控制寄存器及其位定义
************************/
#define SJA_MOD XBYTE[SJA_BASE_ADR 0x00]#define RM_BIT 0x01 //复位模式请求位
#define LOM_BIT 0x02 //只听模式位
#define STM_BIT 0x04 //自检模式位
#define AFM_BIT 0x08 //验收滤波器模式位
#define SM_BIT 0x10 //睡眠模式位/**********************
命令寄存器及其位定义
************************/
#define SJA_CMR XBYTE[SJA_BASE_ADR 0x01]
#define TR_BIT 0x01 //发送请求位
#define AT_BIT 0x02 //中止发送位
#define RRB_BIT 0x04 //释放接收缓冲器位
#define CDO_BIT 0x08 //清除数据溢出位
#define SRR_BIT 0x10 //自身接收请求位/**********************
状态寄存器及其位定义
************************/
#define SJA_SR XBYTE[SJA_BASE_ADR 0x02]
#define RBS_BIT 0x01 //接收缓冲器状态位
#define DOS_BIT 0x02 //数据溢出状态位
#define TBS_BIT 0x04 //发送缓冲器状态位
#define TCS_BIT 0x08 //发送完成状态位
#define RS_BIT 0x10 //接收状态位
#define TS_BIT 0x20 //发送状态位
#define ES_BIT 0x40 //错误状态位
#define BS_BIT 0x80 //总线状态位/**********************
中断寄存器及其位定义
************************/
#define SJA_IR XBYTE[SJA_BASE_ADR 0x03]
#define RI_BIT 0x01 //接收中断位
#define TI_BIT 0x02 //发送中断位
#define EI_BIT 0x04 //错误警告中断位
#define DOI_BIT 0x08 //数据溢出中断位
#define WUI_BIT 0x10 //唤醒中断位
#define EPI_BIT 0x20 //错误消极中断位
#define ALI_BIT 0x40 //仲裁丢失中断位
#define BEI_BIT 0x80 //总线错误中断位/**********************
中断使能寄存器及其位定义
************************/
#define SJA_IER XBYTE[SJA_BASE_ADR 0x04]
#define RIE_BIT 0x01 //接收中断使能位
#define TIE_BIT 0x02 //发送中断使能位
#define EIE_BIT 0x04 //错误警告中断使能位
#define DOIE_BIT 0x08 //数据溢出中断使能位
#define WUIE_BIT 0x10 //唤醒中断使能位
#define EPIE_BIT 0x20 //错误消极中断使能位
#define ALIE_BIT 0x40 //仲裁丢失中断使能位
#define BEIE_BIT 0x80 //总线错误中断使能位#define SJA_BTR0 XBYTE[SJA_BASE_ADR 0x06] //总线定时器0寄存器
#define SJA_BTR1 XBYTE[SJA_BASE_ADR 0x07] //总线定时器1寄存器
#define SAM_BIT 0x80 //采样模式位0总线被采样1次1 总线被采样3次/**********************
输出控制寄存器及其位定义
************************/
#define SJA_OCR XBYTE[SJA_BASE_ADR 0x08]/*OCMODE1 OCMODE0 */
#define BiPhaseMode 0x00 //双相输出模式
#define NormalMode 0x02 //正常输出模式
#define ClkOutMode (0x01|0x02) //时钟输出模式/*TX1 的输出管脚配置*/
#define OCPOL1_BIT 0x20 //输出极性控制位
#define Tx1Float 0x00 //配置为悬空
#define Tx1PullDn 0x40 //配置为下拉
#define Tx1PullUp 0x80 //配置为上拉
#define Tx1PshPull (0x40|0x80) //配置为推挽/*TX0 的输出管脚配置*/
#define OCPOL0_BIT 0x04 //输出极性控制位
#define Tx0Float 0x00 //配置为悬空
#define Tx0PullDn 0x08 //配置为下拉
#define Tx0PullUp 0x10 //配置为上拉
#define Tx0PshPull (0x10|0x08) //配置为推挽#define SJA_TEST XBYTE[SJA_BASE_ADR 0x09] //测试寄存器/********************************* #define SJA_10 XBYTE[SJA_BASE_ADR 0x0a] 寄存器功能保留********************************//**********************
其他寄存器及其位定义
************************/
#define SJA_ALC XBYTE[SJA_BASE_ADR 0x0b] //仲裁丢失捕捉寄存器
#define SJA_ECC XBYTE[SJA_BASE_ADR 0x0c] //错误捕捉寄存器
#define SJA_EWLR XBYTE[SJA_BASE_ADR 0x0d] //错误报警限制寄存器
#define SJA_RXERR XBYTE[SJA_BASE_ADR 0x0e] //RX 错误计数器寄存器
#define SJA_TXERR XBYTE[SJA_BASE_ADR 0x0f] //TX 错误计数器寄存器/**********************
验收滤波器寄存器及其位定义
************************/
#define SJA_ACR0 XBYTE[SJA_BASE_ADR 0x10] //验收代码0寄存器
#define SJA_ACR1 XBYTE[SJA_BASE_ADR 0x11] //验收代码1寄存器
#define SJA_ACR2 XBYTE[SJA_BASE_ADR 0x12] //验收代码2寄存器
#define SJA_ACR3 XBYTE[SJA_BASE_ADR 0x13] //验收代码3寄存器#define SJA_AMR0 XBYTE[SJA_BASE_ADR 0x14] //验收屏蔽0寄存器
#define SJA_AMR1 XBYTE[SJA_BASE_ADR 0x15] //验收屏蔽1寄存器
#define SJA_AMR2 XBYTE[SJA_BASE_ADR 0x16] //验收屏蔽2寄存器
#define SJA_AMR3 XBYTE[SJA_BASE_ADR 0x17] //验收屏蔽3寄存器/**********************
TX缓冲器地址定义
************************/
#define SJA_TBSR0 XBYTE[SJA_BASE_ADR 0x10]
#define SJA_TBSR1 XBYTE[SJA_BASE_ADR 0x11]
#define SJA_TBSR2 XBYTE[SJA_BASE_ADR 0x12]
#define SJA_TBSR3 XBYTE[SJA_BASE_ADR 0x13]
#define SJA_TBSR4 XBYTE[SJA_BASE_ADR 0x14]
#define SJA_TBSR5 XBYTE[SJA_BASE_ADR 0x15]
#define SJA_TBSR6 XBYTE[SJA_BASE_ADR 0x16]
#define SJA_TBSR7 XBYTE[SJA_BASE_ADR 0x17]
#define SJA_TBSR8 XBYTE[SJA_BASE_ADR 0x18]
#define SJA_TBSR9 XBYTE[SJA_BASE_ADR 0x19]
#define SJA_TBSR10 XBYTE[SJA_BASE_ADR 0x1a]
#define SJA_TBSR11 XBYTE[SJA_BASE_ADR 0x1b]
#define SJA_TBSR12 XBYTE[SJA_BASE_ADR 0x1c]/**********************
RX缓冲器地址定义
************************/
#define SJA_RBSR0 XBYTE[SJA_BASE_ADR 0x10]
#define SJA_RBSR1 XBYTE[SJA_BASE_ADR 0x11]
#define SJA_RBSR2 XBYTE[SJA_BASE_ADR 0x12]
#define SJA_RBSR3 XBYTE[SJA_BASE_ADR 0x13]
#define SJA_RBSR4 XBYTE[SJA_BASE_ADR 0x14]
#define SJA_RBSR5 XBYTE[SJA_BASE_ADR 0x15]
#define SJA_RBSR6 XBYTE[SJA_BASE_ADR 0x16]
#define SJA_RBSR7 XBYTE[SJA_BASE_ADR 0x17]
#define SJA_RBSR8 XBYTE[SJA_BASE_ADR 0x18]
#define SJA_RBSR9 XBYTE[SJA_BASE_ADR 0x19]
#define SJA_RBSR10 XBYTE[SJA_BASE_ADR 0x1a]
#define SJA_RBSR11 XBYTE[SJA_BASE_ADR 0x1b]
#define SJA_RBSR12 XBYTE[SJA_BASE_ADR 0x1c]#define SJA_RMC XBYTE[SJA_BASE_ADR 0x1d] //RX 信息计数器 寄存器
#define SJA_RBSA XBYTE[SJA_BASE_ADR 0x1e] //RX 缓冲区起始地址 寄存器/**********************
时钟分频寄存器地址定义
************************/
#define SJA_CDR XBYTE[SJA_BASE_ADR 0x1f] //时钟分频 寄存器
#define CLKOff_BIT 0x08 //时钟关闭位时钟输出管脚控制位
#define RXINTEN_BIT 0x20 //用于接收中断的管脚TX1
#define CBP_BIT 0x40 //CAN 比较器旁路控制位
#define CANMode_BIT 0x80 //CAN 模式控制位/**********************
定义标识符
************************/#define FrameNum 13 //一帧字节数#define Fclk 11059200UL /*使用11.0592M晶体*/
#define BAUD 9600UL /*波特率定义为9600*/#define SmgPort P0 //数码管段seg的引脚-即控制7段加一点形成不同形状
#define SmgCtrl P2 //数码管公共位com的引脚-即选择控制点不点这个数码管//#define const_voice_short 40 //蜂鸣器短叫的持续时间#define KEY_FILTER_TIME1 20 //按键去抖动延时的时间
//#define KEY_FILTER_TIME2 20 //按键去抖动延时的时间
//#define KEY_FILTER_TIME3 20 //按键去抖动延时的时间sbit SJA_RST P2^3;//SJA1000复位管脚
sbit SJA_CS P2^0;//SJA1000片选管脚sbit KEY_INPUT1P3^2;//INT0按键为计数按键--也可以是普通按键//sbit KEY_INPUT1P1^0;
//sbit KEY_INPUT2P1^1;
//sbit KEY_INPUT3P1^2;//sbit beep_drP2^7;//蜂鸣器的驱动 IO 口//sbit led_drP3^5;//作为中途暂停指示灯 亮的时候表示中途暂停
sbit LED_REDP1^0;
sbit LED_GERP1^1; //sbit dig_hc595_sh_drP2^3; //数码管的 74HC595 程序
//sbit dig_hc595_st_drP2^4;
//sbit dig_hc595_ds_drP2^5;//sbit hc595_sh_drP2^0;//LED 灯的 74HC595 程序
//sbit hc595_st_drP2^1;
//sbit hc595_ds_drP2^2;
volatile unsigned char ucDisBuff[4];volatile unsigned char ucPeli_TXD_StatusTemp; //接收数据状态缓存
volatile unsigned char ucPeli_RXD_StatusTemp; //发送数据状态缓存volatile unsigned char bdata ucRegister_StatusTemp;//寄存器数据状态缓存volatile unsigned char ucTxd_Flag0; //数据发送处理标志
volatile unsigned char ucRxd_Flag0; //数据接收处理标志volatile unsigned char ucACRR[4]; //定义数组ACRR,存贮接受代码寄存器内容
volatile unsigned char ucAMRR[4]; //定义数组AMRR,存贮接受屏蔽代码寄存器内容volatile unsigned char ucRX_buffer[FrameNum]; //接收的数据
volatile unsigned char ucTX_buffer[FrameNum]; //接收的数据
volatile unsigned char ucTxd_data0;//CAN总线要发送的数据也是要在数码管1-2位置显示的数据
volatile unsigned char ucRxd_data0;//CAN总线要接收的数据也是要在数码管3-4位置显示的数据volatile unsigned char ucKeySec0;//被触发的按键编号//按键1
volatile unsigned int uiKeyTimeCnt10;//按键去抖动延时计数器
volatile unsigned char ucKeyLock10;//按键触发后自锁的变量标志//按键2
//unsigned int uiKeyTimeCnt20;//按键去抖动延时计数器
//unsigned char ucKeyLock20;//按键触发后自锁的变量标志//按键3
//unsigned int uiKeyTimeCnt30;//按键去抖动延时计数器
//unsigned char ucKeyLock30;//按键触发后自锁的变量标志//蜂鸣器
volatile unsigned int uiVoiceCnt0;//蜂鸣器鸣叫的持续时间计数器//数码管要显示的内容
volatile unsigned char ucDigShow1;//第 1 位数码管要显示的内容
volatile unsigned char ucDigShow2;//第 2 位数码管要显示的内容
volatile unsigned char ucDigShow3;//第 3 位数码管要显示的内容
volatile unsigned char ucDigShow4;//第 4 位数码管要显示的内容
//unsigned char ucDigShow5;//第 5 位数码管要显示的内容
//unsigned char ucDigShow6;//第 6 位数码管要显示的内容
//unsigned char ucDigShow7;//第 7 位数码管要显示的内容
//unsigned char ucDigShow8;//第 8 位数码管要显示的内容//数码管是否显示小数点volatile unsigned char ucDigDot1;//数码管 1 的小数点是否显示的标志
volatile unsigned char ucDigDot2;//数码管 2 的小数点是否显示的标志
volatile unsigned char ucDigDot3;//数码管 3 的小数点是否显示的标志
volatile unsigned char ucDigDot4;//数码管 4 的小数点是否显示的标志
//unsigned char ucDigDot5;//数码管 5 的小数点是否显示的标志
//unsigned char ucDigDot6;//数码管 6 的小数点是否显示的标志
//unsigned char ucDigDot7;//数码管 7 的小数点是否显示的标志
//unsigned char ucDigDot8;//数码管 8 的小数点是否显示的标志volatile unsigned int uiSetData10;//本程序中需要被设置的参数 1
volatile unsigned int uiSetData20;//本程序中需要被设置的参数 2
volatile unsigned int uiSetData30;//本程序中需要被设置的参数 3
volatile unsigned int uiSetData40;//本程序中需要被设置的参数 4volatile unsigned char ucTemp10; //中间过渡变量
volatile unsigned char ucTemp20; //中间过渡变量
volatile unsigned char ucTemp30; //中间过渡变量
volatile unsigned char ucTemp40; //中间过渡变量volatile unsigned char ucDigShowTemp0;//临时中间变量volatile unsigned char ucDisplayDriveStep1;//动态扫描数码管的步骤变量volatile unsigned char ucWd1Update1;//窗口 1 更新显示标志
volatile unsigned char ucWd2Update0;//窗口 2 更新显示标志
volatile unsigned char ucWd3Update0;//窗口 3 更新显示标志
volatile unsigned char ucWd4Update0;//窗口 4 更新显示标志volatile unsigned char ucWd1;//本程序的核心变量窗口显示变量。类似于一级菜单的变量。代表显示不同的窗口。//转换表里面的16个数据转换成二进制后第7位数据都是1默认不显示小数点共阳.
//编码规则是gfedcba ,其中g为小数点控制dp
//数码管是abcdefg
code u8 Cu8DigTable[]
{0xC0, //0 序号00xF9, //1 序号10xA4, //2 序号20xB0, //3 序号30x99, //4 序号40x92, //5 序号50x82, //6 序号60xF8, //7 序号70x80, //8 序号80x90, //9 序号90x88, //A 序号100x83, //B 序号110xC6, //C 序号120xA1, //D 序号130x86, //E 序号140x8E, //F 序号150xFF, //不显示 序号16
};void Init_Sys(); //MCU初始化
void Init_Peripheral(); //外围设备初始化
void Delay_Short(unsigned int uiDelayshort);
void Delay_Long(unsigned int uiDelaylong);//驱动数码管的74HC595
//void dig_hc595_drive(unsigned char ucDigStatusTemp16_09,unsigned char ucDigStatusTemp08_01);void Smg_Scan();//显示数码管字模的驱动函数
void Smg_Service();//显示的窗口菜单服务程序
void LED_Disp_Seg7();//显示子函数
void Led_Show(unsigned char, unsigned char);//驱动LED的74HC595
//void hc595_drive(unsigned char ucLedStatusTemp16_09,unsigned char ucLedStatusTemp08_01);
void T0timer_Service();//定时中断函数void Key_Service();//按键服务的应用程序
void key_Scan();//按键扫描函数 放在定时中断里void Peli_TXDService(void); //发送处理函数
void Peli_RXDService(void); //接收处理函数void Peli_TXDScan(void);//CAN发送子任务函数
void Peli_RXDScan(void);//CAN接收子驱动函数void main()
{Init_Sys();Delay_Short(10);Init_Peripheral();while(1) {Key_Service();//按键服务的应用程序 Peli_TXDService(); //发送处理函数Peli_RXDService(); //接收处理函数Smg_Service();//显示的窗口菜单服务程序 //Led_Show(0, ucTxd_data);//Led_Show(1,ucRxd_data);}
}void key_Scan()//按键扫描函数 放在定时中断里
{//按键1扫描if(KEY_INPUT11)//IO 是高电平说明按键没有被按下这时要及时清零一些标志位 {ucKeyLock10;//按键自锁标志清零 uiKeyTimeCnt10;//按键去抖动延时计数器清零此行非常巧妙是我实战中摸索出来的。 } else if(ucKeyLock10)//有按键按下且是第一次被按下 {uiKeyTimeCnt1;//累加定时中断次数 if(uiKeyTimeCnt1KEY_FILTER_TIME1) {uiKeyTimeCnt10;ucKeyLock11;//自锁按键置位,避免一直触发 ucKeySec1;//触发 1 号键 }}
}
/*//按键2扫描if(KEY_INPUT21)//IO 是高电平说明按键没有被按下这时要及时清零一些标志位 {ucKeyLock20;//按键自锁标志清零 uiKeyTimeCnt20;//按键去抖动延时计数器清零此行非常巧妙是我实战中摸索出来的。 } else if(ucKeyLock20)//有按键按下且是第一次被按下 {uiKeyTimeCnt2;//累加定时中断次数 if(uiKeyTimeCnt2KEY_FILTER_TIME2) {uiKeyTimeCnt20;ucKeyLock21;//自锁按键置位,避免一直触发 ucKeySec2;//触发 2 号键 }}//按键3扫描if(KEY_INPUT31)//IO 是高电平说明按键没有被按下这时要及时清零一些标志位 {ucKeyLock30;//按键自锁标志清零 uiKeyTimeCnt30;//按键去抖动延时计数器清零此行非常巧妙是我实战中摸索出来的。 } else if(ucKeyLock30)//有按键按下且是第一次被按下 {uiKeyTimeCnt3;//累加定时中断次数 if(uiKeyTimeCnt3KEY_FILTER_TIME3) {uiKeyTimeCnt30;ucKeyLock31;//自锁按键置位,避免一直触发 ucKeySec3;//触发 3 号键 }}
}
*/void Key_Service() //按键服务的应用程序
{switch(ucKeySec) //按键服务状态切换 { //按键1case 1:// 加按键 对应朱兆祺学习板的 S1 键switch(ucWd) //在不同的窗口下设置不同的参数 { //窗口 1 case 1://uiSetData1;ucTxd_data;//发送的数据加1if(ucTxd_data99) //最大值是 9999 {ucTxd_data 99;}uiSetData1 ucTxd_data; //存储计数结果并为待发送的数据ucTxd_Flag 1; // //发送标志置1准备发生ucWd1Update1;//窗口 1 更新显示 break;
/*//窗口 2 case 2:uiSetData2;if(uiSetData29999) //最大值是 9999 {uiSetData29999;}ucWd2Update1;//窗口 2 更新显示 break;//窗口 3 case 3:uiSetData3;if(uiSetData39999) //最大值是 9999 {uiSetData39999;}ucWd3Update1;//窗口 3 更新显示 break;//窗口 4 case 4:uiSetData4;if(uiSetData49999) //最大值是 9999 {uiSetData49999;}ucWd4Update1;//窗口 4 更新显示 break;
*/}//uiVoiceCntconst_voice_short;//按键声音触发滴一声就停。 ucKeySec0;//响应按键服务处理程序后按键编号清零避免一致触发 break;
/* //按键2case 2:// 减按键 对应朱兆祺学习板的 S5 键switch(ucWd) //在不同的窗口下设置不同的参数 { //窗口 1case 1:uiSetData1--;if(uiSetData19999) {uiSetData10;//最小值是 0 }ucWd1Update1;//窗口 1 更新显示 break;//窗口 2case 2:uiSetData2--;if(uiSetData29999) {uiSetData20;//最小值是 0 }ucWd2Update1;//窗口 2 更新显示 break;//窗口 3case 3:uiSetData3--;if(uiSetData39999) {uiSetData30;//最小值是 0 }ucWd3Update1;//窗口 3 更新显示 break;//窗口 4case 4:uiSetData4--;if(uiSetData49999) {uiSetData40;//最小值是 0 }ucWd4Update1;//窗口 4 更新显示 break;}//uiVoiceCntconst_voice_short;//按键声音触发滴一声就停ucKeySec0;//响应按键服务处理程序后按键编号清零避免一致触发 break;
*/
/*//按键3case 3:// 切换窗口按键 对应朱兆祺学习板的 S9 键ucWd;//切换窗口 if(ucWd4) {ucWd1;}switch(ucWd) //在不同的窗口下在不同的窗口下更新显示不同的窗口 {case 1:ucWd1Update1;//窗口 1 更新显示break;case 2:ucWd2Update1; //窗口 2 更新显示 break;case 3:ucWd3Update1;//窗口 3 更新显示 break;case 4:ucWd4Update1;//窗口 4 更新显示 break;}uiVoiceCntconst_voice_short;//按键声音触发滴一声就停。 ucKeySec0;//响应按键服务处理程序后按键编号清零避免一致触发 break;
*/}
}/* 注释二
*鸿哥首次提出的一二级菜单显示理论
*凡是人机界面显示不管是数码管还是液晶屏都可以把显示的内容分成不同的窗口来显示
*每个显示的窗口中又可以分成不同的局部显示。其中窗口就是一级菜单用ucWd变量表示。
*局部就是二级菜单用ucPart来表示。不同的窗口会有不同的更新显示变量ucWdXUpdate来对应
*表示整屏全部更新显示。
*不同的局部也会有不同的更新显示变量ucWdXPartYUpdate来对应表示局部更新显示。
*/void Smg_Service() //显示的窗口菜单服务程序
{switch(ucWd) //本程序的核心变量窗口显示变量。类似于一级菜单的变量。代表显示不同的窗口。 {case 1: //窗口1显示 P--1 窗口的数据if(ucWd1Update1) //窗口 1 要全部更新显示 {ucWd1Update0;//及时清零标志避免一直进来扫描 //ucDigShow812;//第 8 位数码管显示 P - ucTemp816; //显示空 //ucDigShow711;//第 7 位数码管显示- ucTemp716; //显示空//ucDigShow61;//第 6 位数码管显示 1 ucTemp616; //显示空//ucDigShow510;//第 5 位数码管显示无 ucTemp516; //显示空//分解数据//ucTemp4uiSetData1/1000;//取千位// ucTemp3uiSetData1%1000/100; //取百位ucTemp4uiSetData2%100/10; //取十位ucTemp3uiSetData2%10; //取个位ucTemp2uiSetData1%100/10; //取十位ucTemp1uiSetData1%10; //取个位//把数据分配到数码管//第 4 位数码管要显示的内容/*if(uiSetData11000) {ucDigShow410;//如果小于 1000千位显示无 } else {ucDigShow4ucTemp4;//第 4 位数码管要显示的内容 }//第 3位数码管要显示的内容if(uiSetData1100) {ucDigShow310;//如果小于 100百位显示无 } else {ucDigShow3ucTemp3;//第 3 位数码管要显示的内容 }*///第 4 位数码管要显示的内容if(uiSetData210) {ucDigShow416;//如果小于 16十位显示无 这里根据 数据表来的也可以填10 } else {ucDigShow4ucTemp4;//第 4 位数码管要显示的内容 }//第 3 位数码管要显示的内容ucDigShow3ucTemp3;//第 3位数码管要显示的内容 //第 2 位数码管要显示的内容if(uiSetData110) {ucDigShow216;//如果小于 16十位显示无 } else {ucDigShow2ucTemp2;//第 2 位数码管要显示的内容 }//第 1 位数码管要显示的内容ucDigShow1ucTemp1;//第 1 位数码管要显示的内容 }break;/*//就使用一个窗口2,3,4窗口可以关闭case 2: //显示 P--2 窗口的数据if(ucWd2Update1) //窗口 2 要全部更新显示 {ucWd2Update0;//及时清零标志避免一直进来扫描 ucDigShow812;//第 8 位数码管显示 P ucDigShow711;//第 7 位数码管显示- ucDigShow62;//第 6 位数码管显示 2 ucDigShow510;//第 5 位数码管显示无 ucTemp4uiSetData2/1000;//分解数据 ucTemp3uiSetData2%1000/100;ucTemp2uiSetData2%100/10;ucTemp1uiSetData2%10;if(uiSetData21000) {ucDigShow410;//如果小于 1000千位显示无 } else {ucDigShow4ucTemp4;//第 4 位数码管要显示的内容 }if(uiSetData2100) {ucDigShow310;//如果小于 100百位显示无 } else {ucDigShow3ucTemp3;//第 3 位数码管要显示的内容 }if(uiSetData210) {ucDigShow210;//如果小于 10十位显示无 } else {ucDigShow2ucTemp2;//第 2 位数码管要显示的内容 }ucDigShow1ucTemp1;//第 1 位数码管要显示的内容 }break;case 3: //显示 P--3 窗口的数据if(ucWd3Update1) //窗口 3 要全部更新显示 {ucWd3Update0;//及时清零标志避免一直进来扫描 ucDigShow812;//第 8 位数码管显示 P ucDigShow711;//第 7 位数码管显示- ucDigShow63;//第 6 位数码管显示 3 ucDigShow510;//第 5 位数码管显示无 ucTemp4uiSetData3/1000;//分解数据 ucTemp3uiSetData3%1000/100;ucTemp2uiSetData3%100/10;ucTemp1uiSetData3%10;if(uiSetData31000) {ucDigShow410;//如果小于 1000千位显示无 }else{ucDigShow4ucTemp4;//第 4 位数码管要显示的内容 }if(uiSetData3100) {ucDigShow310;//如果小于 100百位显示无} else {ucDigShow3ucTemp3;//第 3 位数码管要显示的内容 }if(uiSetData310) {ucDigShow210;//如果小于 10十位显示无} else {ucDigShow2ucTemp2;//第 2 位数码管要显示的内容 }ucDigShow1ucTemp1;//第 1 位数码管要显示的内容 }break;case 4: //显示 P--4 窗口的数据if(ucWd4Update1) //窗口 4 要全部更新显示 {ucWd4Update0;//及时清零标志避?庖恢苯瓷? ucDigShow812;//第 8 位数码管显示 P ucDigShow711;//第 7 位数码管显示- ucDigShow64;//第 6 位数码管显示 4 ucDigShow510;//第 5 位数码管显示无 ucTemp4uiSetData4/1000;//分解数据 ucTemp3uiSetData4%1000/100;ucTemp2uiSetData4%100/10;ucTemp1uiSetData4%10;if(uiSetData41000) {ucDigShow410;//如果小于 1000千位显示无 } else {ucDigShow4ucTemp4;//第 4 位数码管要显示的内容 }if(uiSetData4100) {ucDigShow310;//如果小于 100百位显示无 } else {ucDigShow3ucTemp3;//第 3 位数码管要显示的内容 }if(uiSetData410) {ucDigShow210;//如果小于 10十位显示无 } else {ucDigShow2ucTemp2;//第 2 位数码管要显示的内容 }ucDigShow1ucTemp1;//第 1 位数码管要显示的内容 }break;
*/}
}/* 注释一
* 动态驱动数码管的原理是在八位数码管中在任何一个瞬间每次只显示其中一位数码管
* 另外的七个数码管通过设置其公共位com为高电平来关闭显示
* 只要切换画面的速度足够快人的视觉就分辨不出来感觉八个数码管 是同时亮的。
* 以下dig_hc595_drive(xx,yy函数
* 其中第一个形参xx是驱动数码管段seg的引脚第二个形参yy是驱动 数码管公共位com的引脚。
*/void Smg_Drive()
{//以下程序如果加一些数组和移位的元素还可以压缩容量。//但是鸿哥追求的不是容量而是清晰的讲解思路//共阴数码管-- 想让第7位置1其它位保持不变只需跟十六进制的0x80相“或”:bb | 0x80//共阳数码管-- 想让第7位清零其它位保持不变只需跟十六进制的0x7f相“与”:bb 0x7fswitch(ucDisplayDriveStep) {case 1: //显示第 1 位ucDigShowTempCu8DigTable[ucDigShow1]; //根据要显示的内容取数if(ucDigDot11) //判断是否要小数点{ucDigShowTempucDigShowTemp 0x7f;//显示小数点 }//dig_hc595_drive(ucDigShowTemp,0xfe);SmgPort ucDigShowTemp; // 送P0端口SmgCtrl SmgCtrl 0x7f; //打开数码管Delay_Short(50); //打开一会儿这里数据越大越亮SmgCtrl SmgCtrl | 0xf0; //关闭break;case 2: //显示第 2 位ucDigShowTempCu8DigTable[ucDigShow2]; //根据要显示的内容取数if(ucDigDot21) //判断是否要小数点{ucDigShowTempucDigShowTemp 0x7f;//显示小数点 }//dig_hc595_drive(ucDigShowTemp,0xfd);SmgPort ucDigShowTemp; // 送P0端口SmgCtrl SmgCtrl 0xbf; //打开数码管 Delay_Short(50); //打开一会儿这里数据越大越亮SmgCtrl SmgCtrl | 0xf0; //关闭break;case 3: //显示第 3 位ucDigShowTempCu8DigTable[ucDigShow3]; //根据要显示的内容取数if(ucDigDot31) //判断是否要小数点{ucDigShowTempucDigShowTemp 0x7f; //显示小数点 }//dig_hc595_drive(ucDigShowTemp,0xfb);SmgPort ucDigShowTemp; // 送P0端口SmgCtrl SmgCtrl 0xdf; //打开数码管Delay_Short(50); //打开一会儿这里数据越大越亮SmgCtrl SmgCtrl | 0xf0; //关闭break;case 4: //显示第 4 位ucDigShowTempCu8DigTable[ucDigShow4]; //根据要显示的内容取数if(ucDigDot41) //判断是否要小数点{ucDigShowTempucDigShowTemp 0x7f;//显示小数点 }//dig_hc595_drive(ucDigShowTemp,0xf7);SmgPort ucDigShowTemp; // 送P0端口SmgCtrl SmgCtrl 0xef; //打开数码管Delay_Short(50); //打开一会儿,z这里数据越大越亮SmgCtrl SmgCtrl | 0xf0; //关闭break;
/* case 5: //显示第 5 位ucDigShowTempCu8DigTable[ucDigShow5];if(ucDigDot51) {ucDigShowTempucDigShowTemp|0x80;//显示小数点 }dig_hc595_drive(ucDigShowTemp,0xef);break;case 6: //显示第 6 位ucDigShowTempCu8DigTable[ucDigShow6];if(ucDigDot61) {ucDigShowTempucDigShowTemp|0x80;//显示小数点 }dig_hc595_drive(ucDigShowTemp,0xdf);break;case 7: //显示第 7 位ucDigShowTempCu8DigTable[ucDigShow7];if(ucDigDot71) {ucDigShowTempucDigShowTemp|0x80;//显示小数点 }dig_hc595_drive(ucDigShowTemp,0xbf);break;case 8: //显示第 8 位ucDigShowTempCu8DigTable[ucDigShow8];if(ucDigDot81) {ucDigShowTempucDigShowTemp|0x80;//显示小数点 }dig_hc595_drive(ucDigShowTemp,0x7f);break;
*/}ucDisplayDriveStep;if(ucDisplayDriveStep4) //扫描完 44 个数码管后重新从第一个开始扫描 {ucDisplayDriveStep1;}
}/*
//数码管的 74HC595 驱动函数
void dig_hc595_drive(unsigned char ucDigStatusTemp16_09,unsigned char ucDigStatusTemp08_01)
{unsigned char i;unsigned char ucTempData;dig_hc595_sh_dr0;dig_hc595_st_dr0;ucTempDataucDigStatusTemp16_09;//先送高 8 位 for (i0;i8;i) {if(ucTempData0x80)dig_hc595_ds_dr1; else dig_hc595_ds_dr0;dig_hc595_sh_dr0;//SH 引脚的上升沿把数据送入寄存器 Delay_Short(1);dig_hc595_sh_dr1;Delay_Short(1);ucTempDataucTempData1;}ucTempDataucDigStatusTemp08_01;//再先送低 8 位 for (i0;i8;i) {if(ucTempData0x80)dig_hc595_ds_dr1; else dig_hc595_ds_dr0;dig_hc595_sh_dr0;//SH 引脚的上升沿把数据送入寄存器 Delay_Short(1);dig_hc595_sh_dr1;Delay_Short(1);ucTempDataucTempData1;}dig_hc595_st_dr0;//ST 引脚把两个寄存器的数据更新输出到 74HC595 的输出引脚上并且锁存起来 Delay_Short(1);dig_hc595_st_dr1;Delay_Short(1);dig_hc595_sh_dr0;//拉低抗干扰就增强 dig_hc595_st_dr0;dig_hc595_ds_dr0;
}
//LED 灯的 74HC595 驱动函数
void hc595_drive(unsigned char ucLedStatusTemp16_09,unsigned char ucLedStatusTemp08_01)
{unsigned char i;unsigned char ucTempData;hc595_sh_dr0;hc595_st_dr0;ucTempDataucLedStatusTemp16_09;//先送高 8 位 for (i0;i8;i) {if(ucTempData0x80)hc595_ds_dr1; else hc595_ds_dr0;hc595_sh_dr0;//SH 引脚的上升沿把数据送入寄存器 Delay_Short(1);hc595_sh_dr1;Delay_Short(1);ucTempDataucTempData1;}ucTempDataucLedStatusTemp08_01;//再先送低 8 位 for (i0;i8;i) {if(ucTempData0x80)hc595_ds_dr1; else hc595_ds_dr0;hc595_sh_dr0;//SH 引脚的上升沿把数据送入寄存器 Delay_Short(1);hc595_sh_dr1;Delay_Short(1);ucTempDataucTempData1;}hc595_st_dr0;//ST 引脚把两个寄存器的数据更新输出到 74HC595 的输出引脚上并且锁存起来 Delay_Short(1);hc595_st_dr1;Delay_Short(1);hc595_sh_dr0;//拉低抗干扰就增强 hc595_st_dr0;hc595_ds_dr0;
}
*///数码管显示函数2
//void LED_Disp_Seg7()
//{
// SmgCtrl SmgCtrl | 0xf0;// DisBuff[0] Txd_data%10;//取个位数
// DisBuff[1] Txd_data%100/10; //取十位数
//
// DisBuff[2] Rxd_data%10; //百位数
// DisBuff[3] Rxd_data%100/10; //千位数
//
// SmgPort Cu8DigTable[DisBuff[0]];
// SmgCtrl SmgCtrl 0x7f;
// Delay(5);
// SmgCtrl SmgCtrl | 0xf0;// SmgPort Cu8DigTable[DisBuff[1]];
// SmgCtrl SmgCtrl 0xbf;
// Delay(5);
// SmgCtrl SmgCtrl | 0xf0;// SmgPort Cu8DigTable[DisBuff[2]];
// SmgCtrl SmgCtrl 0xdf;
// Delay(5);
// SmgCtrl SmgCtrl | 0xf0;// SmgPort Cu8DigTable[DisBuff[3]];
// SmgCtrl SmgCtrl 0xef;
// Delay(5);
// SmgCtrl SmgCtrl | 0xf0;
//}//数码管显示函数3
//http://blog.chinaunix.net/uid/22889411/cid-2388-list-4.html
/*这个显示有点绕
from(1_4)数码管显示起始位置从右到左number显示的数数码管上采用10进制显示//void Smg_Show(uchar from,uchar number)
//{
// uchar GetCode,temp_l;
// uchar temp_h0x7f; //初值0111 1111
// temp_h _cror_(temp_h,from-1); //右移, //确定从哪一位开始显示即确定高四位
// temp_h temp_h 0xf0; //取高四位
// temp_l P2 0x0f; //取P2的低四位这里是想不动的继承低4位的数据。
// P2 temp_h | temp_l; //设定P2口// if(number0)
// {
// P0 led[0];
// Delay(10);
// P0 0xff;
// }
// else
// {
// while(number)
// {
// GetCode number%10 ;
// number / 10;
// P0 led[GetCode] ;
// Delay(10);
//
//
// temp_h P2 0xf0; // 与 1111 0000 低四位 清0 即保持高四位取P2的高四位
// temp_h temp_h | 0x0f; //取P2的高四位后再或 0000 1111 拼装 temp_h进行位选
// temp_h _cror_(temp_h,1);
// temp_h temp_h 0xf0; //取高四位
// temp_l P2 0x0f; //取P2的低四位
// P0 0xff;
// P2 temp_h | temp_l; //设定P2口
// }
// }
//
//}*/
https://www.360docs.net/doc/10803116.html
//void Led_Show(unsigned char wela,unsigned char number)
//{
// unsigned char digit;
// unsigned char temp;// //第三个数码管单独加上小数点
//
// //没想到怎么写
//
// if(wela) //高位显示即数码管 1-2
// {
// temp 0x7b; //temp0111 1011B
// }
// else//低位显示即数码管 3-4
// {
// temp 0xde; //temp1101 1110B
// }//
// //数码管个位显示
// digit number%10;
// SmgPort Cu8DigTable[digit];
// SmgCtrl (temp | 0x0f) SmgCtrl;//开个位,或0-保留其本身,保留了高四位
// Delay_Short(5);
// SmgCtrl 0xff;
// SmgPort 0xff; //关闭个位数码管十位显示
// if( number 10) //先判断十位要不要显示就是数据大于10不
// {
// SmgCtrl 0xff;
// }
// else
// {
// digit number%100/10;
// //SmgPort Cu8DigTable[digit]0x7f;//这样写2个十位都加了小数点,0x80 ,是共阴 7f 是共阳
// SmgPort Cu8DigTable[digit];
// SmgCtrl ((temp 4)|0x0f) SmgCtrl; //开十位左移四位原本的低四位到高四位 ,
// Delay_Short(5);
// SmgPort 0xff;
// SmgCtrl 0xff;//关闭十位
// }
//
//}//发送处理
void Peli_TXDService() // 定义发送处理函数程序//主要是检测发送标志状态位如果置位则准备数据进行发送数据处理//并且调用发送函数
{if( 1 ucTxd_Flag ) // 若Txd_flag 1,则要求进行数据的发送处理{Delay_Short(1); // 延时ucTxd_Flag 0; // Txd_flag 清零以便下次查询//ucTX_buffer[5] Txd_data; 有些程序有这句话有些没有为啥Peli_TXDScan();//调用CAN发送子任务函数发送数据帧Delay_Short(1); //延时Delay_Short(1); //发送 扩展 数据帧 后SJA1000将产生接收中断}
}//接受处理
void Peli_RXDService()
{if(ucRxd_Flag) // vGu8Rxd_Flag 0,表示无数据可以接收// vGu8Rxd_Flag 1,表示有数据可以接收{EX1 0; // 关闭外部中断ucRxd_Flag 0; // RXD_flag 清零以便下次查询ucRxd_data ucRX_buffer[5]; // CAN总线接收的数据也是要在数码管3和4位置显示的数据uiSetData2 ucRxd_data; //接收的数据送到数码管的显示内容缓存中EX1 1; // 重新开启外部中断}
}//发送数据函数
void Peli_TXDScan( )
{//初始化标示码头信息ucTX_buffer[0] 0x88;//.70扩展帧.60数据帧; .31数据长度ucTX_buffer[1] 0x01;//本节点地址ucTX_buffer[2] 0x02;//ucTX_buffer[3] 0x03;//ucTX_buffer[4] 0x04;////初始化发送数据单元ucTX_buffer[5] ucTxd_data;ucTX_buffer[6] 0x22;ucTX_buffer[7] 0x33;ucTX_buffer[8] 0x44;//ucTX_buffer[9] 0x55;//ucTX_buffer[10] 0x66;//ucTX_buffer[11] 0x77;//ucTX_buffer[12] 0x88;//do{ucPeli_TXD_StatusTemp SJA_SR;LED_RED 0;}while( ucPeli_TXD_StatusTemp RS_BIT); //SR.41 正在接收等待do{ucPeli_TXD_StatusTemp SJA_SR;LED_RED 0;}while(!(ucPeli_TXD_StatusTemp TCS_BIT)); //SR.30,发送请求未处理完等待do{ucPeli_TXD_StatusTemp SJA_SR;LED_RED 0;}while(!(ucPeli_TXD_StatusTemp TBS_BIT)); //SR.20,发送缓冲器被锁。等待LED_GER !LED_GER;LED_RED !LED_RED; SJA_TBSR0 ucTX_buffer[0];SJA_TBSR1 ucTX_buffer[1];SJA_TBSR2 ucTX_buffer[2];SJA_TBSR3 ucTX_buffer[3];SJA_TBSR4 ucTX_buffer[4];SJA_TBSR5 ucTX_buffer[5];SJA_TBSR6 ucTX_buffer[6];SJA_TBSR7 ucTX_buffer[7];SJA_TBSR8 ucTX_buffer[8];SJA_TBSR9 ucTX_buffer[9];SJA_TBSR10 ucTX_buffer[10];SJA_TBSR11 ucTX_buffer[11];SJA_TBSR12 ucTX_buffer[12];SJA_CMR SRR_BIT;//置位自发送接收请求
}//接收数据函数在中断服务程序中调用
void Peli_RXDScan() interrupt 2
{EX1 0;//关CPU中断IE1 0;//中断请求标志清0ucPeli_RXD_StatusTemp SJA_IR;if(ucPeli_RXD_StatusTemp RI_BIT){//IR.0 1 接收中断ucRX_buffer[0] SJA_RBSR0;ucRX_buffer[1] SJA_RBSR1;ucRX_buffer[2] SJA_RBSR2;ucRX_buffer[3] SJA_RBSR3;ucRX_buffer[4] SJA_RBSR4;ucRX_buffer[5] SJA_RBSR5;ucRX_buffer[6] SJA_RBSR6;ucRX_buffer[7] SJA_RBSR7;ucRX_buffer[8] SJA_RBSR8;ucRX_buffer[9] SJA_RBSR9;ucRX_buffer[10] SJA_RBSR10;ucRX_buffer[11] SJA_RBSR11;ucRX_buffer[12] SJA_RBSR12;ucRxd_Flag 1;SJA_CMR RRB_BIT;ucPeli_RXD_StatusTemp SJA_ALC;//释放仲裁随时捕捉寄存器ucPeli_RXD_StatusTemp SJA_ECC;//释放错误代码捕捉寄存器}SJA_IER RIE_BIT;// .01--接收中断使能//Rxd_data RX_buffer[5];EX1 1;//打开CPU中断
}void T0timer_Service() interrupt 1
{TF00;//清除中断标志 TR00;//关中断 key_Scan();//按键扫描函数 Smg_Drive();//数码管字模的驱动函数
/* if(uiVoiceCnt!0) {uiVoiceCnt--;//每次进入定时中断都自减 1直到等于零为止。才停止鸣叫 beep_dr0;//蜂鸣器是 PNP 三极管控制低电平就开始鸣叫} else { beep_dr1; }
*/ TH00xfe;//重装初始值(65535-500)650350xfe0b TL00x0b;TR01;//开中断
}
void Delay_Short(unsigned int uiDelayshort)
{unsigned int i;for (i0;iuiDelayshort;i) {;//一个分号相当于执行一条空语句 }
}
void Delay_Long(unsigned int uiDelaylong)
{unsigned int i;unsigned int j;for (i0;iuiDelaylong;i) {for (j0;j500;j) //内嵌循环的空指令数量 {;//一个分号相当于执行一条空语句 }}
}
void Init_Sys() //第一区 初始化单片机
{SJA_RST 0;//SJA1000复位有效Delay_Short(10); //延时SJA_RST 1;//CAN总线复位管脚,复位无效SJA_CS 0;//CAN总线片选有效EX1 1;//外部中断1使能CAN总线接收中断IT1 0;//CAN总线接收中断低电平触发PX11; // 外部中断最高优先级//IT0 1;//外部中断0负边沿触发//EX0 1;//打开外部中断0//定时器0配置TMOD0x01;//设置定时器 0 为工作方式 1 //TH00xfc; //TL00x66; TH00xfe;//重装初始值(65535-500)650350xfe0b TL00x0b;//中断配置 ET01; //定时器0中断使能TR01; //开定时器0 EA 1; //打开总中断//led_dr0;//关闭独立 LED 灯 //beep_dr1;//用 PNP 三极管控制蜂鸣器输出高电平时不叫。 //hc595_drive(0x00,0x00);//关闭所有经过另外两个 74HC595 驱动的 LED 灯 }
void Init_Peripheral() //第二区 初始化外围
{//static u8 bdata sGu8Register_Status;ucACRR[0] 0x11;ucACRR[1] 0x22;ucACRR[2] 0x33;ucACRR[3] 0x44; //设置节点1的接收代码寄存器值ucAMRR[0] 0xff; ucAMRR[1] 0xff;ucAMRR[2] 0xff;ucAMRR[3] 0xff; //设置节点1的屏蔽代码寄存器值do{// .01---reset MODRe,进入复位模式以便设置相应的寄存器//防止未进入复位模式重复写入SJA_MOD RM_BIT |AFM_BIT;ucRegister_StatusTemp SJA_MOD ;}while(!(ucRegister_StatusTemp RM_BIT));SJA_CDR CANMode_BIT|CLKOff_BIT;// CDR.31--时钟关闭, .70---basic CAN, .71---Peli CAN 时钟分频SJA_BTR0 0x03;SJA_BTR1 0x1c;//16M晶振波特率125KbpsSJA_IER RIE_BIT;// .01--接收中断使能 .10--关闭发送中断使能SJA_OCR NormalMode|Tx0PullDn|OCPOL1_BIT|Tx1PullUp;//0xaa 配置输出控制寄存器SJA_CMR RRB_BIT;//释放接收缓冲器SJA_ACR0 ucACRR[0];SJA_ACR1 ucACRR[1];SJA_ACR2 ucACRR[2];SJA_ACR3 ucACRR[3];//初始化标示码 验收代码寄存器SJA_AMR0 ucAMRR[0];SJA_AMR1 ucAMRR[1];SJA_AMR2 ucAMRR[2];SJA_AMR3 ucAMRR[3];//初始化掩码 验收屏蔽寄存器do //确保进入自接收模式{ SJA_MOD STM_BIT;ucRegister_StatusTemp SJA_MOD;}while( !(ucRegister_StatusTemp STM_BIT) );ucDigDot10; ucDigDot20;ucDigDot30;ucDigDot40;ucDigDot50;//ucDigDot60;//ucDigDot70;//ucDigDot80; //小数点全部不显示 EA1;//开总中断 ET01;//允许定时中断 TR01;//启动定时中断 }
这是源代码按了2次后
这是修改后的代码按了2次后 反正咋说呢想了很久没想明白难道自收发的同步显示其实有问题 就应该有个差值
还是移植的那个数码管程序多了一个变量缘故