📄 main.lst
字号:
1: // ========CAN通信程序=======
2: #include <pic.h>
3: #include <pic1687x.h>
4: #include <mcp2510.h> // MCP2510寄存器定义
5: // =========常数和变量定义=========
6: #define READ 0x03 // 读MCP2510指令代码
7: #define WRITE 0x02 // 写MCP2510指令代码
8: #define RESET 0xC0 // 复位MCP2510指令代码
9: #define RTS 0x80 // MCP2510请求发送指令代码
10: #define STA2510 0xA0 // 读MCP2510状态指令代码
11: #define BITMOD 0x05 // MCP2510位修改指令代码
12: int a[12]; // SPI发送或接收数据寄存器
13: int b[8]; // 发送或接收的数据
14: int c[8]; // 发送或接收的数据
15: int i; // 临时变量
16: int count; // 发送接收计数器
17: int count1=0; // for test
18: int RecID_H=0;
19: int RecID_L=0;
20: int DLC=8;
21: void SPIINT();
22: void TMR1INT();
23: void CCP1INT();
24: void SPIEXCHANGE(int count);
25: void WAIT_SPI();
26: void RESET2510();
27: int RD2510(int adress,int n);
28: void WR2510(int adress,int n);
29: void RTS2510(int RTSn);
30: int GETS2510();
31: void BM2510(int adress,int mask,int data);
32: void SETNORMAL();
33: void TXCOMPLETE(int adress);
34: void TXMSG(int DLC);
35: int RXMSG();
36: void INIT2510();
37: void INIT877();
38: void INITSPI();
39: void ACK();
40: void wait();
41: // ========主程序=======
42: main(void)
43: {
44: int l,detect=0;
45: SSPIE=1;
46: TMR1IE=1;
47: CCP1IE=1;
48: CCP2IE=1;
49: PEIE=1;
50: ei(); // 开中断
51: INIT877(); // 初始化PIC16F877芯片
52: INITSPI(); // 初始化SPI接口
53: INIT2510(); // 初始化MCP2510芯片
54: flag1=0;
55: flag2=0;
56: CCP1CON=0x05;
57: CCP2CON=0x04;
58: while(1) {
59: RXMSG();
60: TXMSG(8);
61: }
62: }
63: // ========中断服务程序=======
64: // SPI中断服务子程序
65: void SPIINT()
66: {
67: SSPIF=0;
68: a[i++]=SSPBUF; // 数据暂存a[]中
69: count-=1;
70: if(count>0) SSPBUF=a[i];// 未发送完,继续
71: else RE2=1; // 否则,片选信号置高电平
72: return;
73: }
74: // TMR1中断服务子程序
75: void TMR1INT()
76: {
77: TMR1IF=0;
78: T1CON=0;
79: if(!flag1){
80: TMR1H=0xfe; // 512 μs 脉冲宽度
81: TMR1L=0x00;
82: T1CON=0x01;
83: PORTD=0xff; // 输出所有通道
84: flag1=1;
85: }
86: else {
87: flag1=0;
88: PORTD=0;
89: T1CON=0;
90: }
91: return;
92: }
93: // CCP1中断服务子程序
94: void CCP1INT()
95: {
96: CCP1IF=0;
97: T1CON=0x01;
98: return;
99: }
100: // CCP2中断服务子程序
101: void CCP2INT()
102: {
103: CCP2IF=0;
104: T1CON=0x01;
105: return;
106: }
107: // 中断入口,保护现场,判中断类型
108: void interrupt INTS()
109: {
110: di();
111: if(TMR1IF) TMR1INT(); // 定时器TMR1中断
112: else if(CCP1IF) CCP1INT(); // 电压过零捕捉中断1
113: else if(CCP2IF) CCP2INT(); // 电压过零捕捉中断2
114: else if(SSPIF) SPIINT(); // SPI接口中断
115: ei();
116: }
117: // ========子程序=======
118: // 启动SPI传送
119: void SPIEXCHANGE(count)
120: int count;
121: {
122: if(count>0) { // 有数据可送?
123: i=0;
124: RE2=0; // 片选位置低电平
125: SSPBUF=a[i]; // 送数
126: }
127: else
128: ; // 否则,空操作,并返回
129: return;
130: }
131: // 等待SPI传送完成
132: void WAIT_SPI()
133: {
134: do{
135: ;
136: }while(count>0); // 当count!=0时,等待 to add "CLRWDT"
137: return;
138: }
139: // 对MCP2510芯片进行复位
140: void RESET2510()
141: {
142: a[0]=RESET;
143: count=1;
144: SPIEXCHANGE(count); // 送复位指令
145: WAIT_SPI();
146: return;
147: }
148: // 读取从地址"adress"开始的寄存器中的数据,共n个,存放在数组b[n]中
149: int RD2510(adress,n)
150: int adress;
151: int n;
152: {
153: int j;
154: a[0]=READ;
155: a[1]=adress;
156: for(j=0;j<n;j++) a[j+2]=0;
157: count=n+2; // 指令、地址和要得到的数据量n
158: SPIEXCHANGE(count);
159: WAIT_SPI();
160: for(j=0;j<n;j++) b[j]=a[j+2];// 数据存到数组b[]中
161: return;
162: }
163: // 向从地址"adress"开始的寄存器写入数据,共n个,数据存放数组b[n]中
164: void WR2510(adress,n)
165: int adress;
166: int n;
167: {
168: int j;
169: a[0]=WRITE;
170: a[1]=adress;
171: for(j=0;j<n;j++) a[j+2]=b[j];
172: count=n+2; // 指令、地址和要写入的数据量n
173: SPIEXCHANGE(count);
174: WAIT_SPI();
175: return;
176: }
177: // MCP2510芯片请求发送程序
178: void RTS2510(RTSn)
179: int RTSn;
180: {
181: a[0]=RTS^RTSn;
182: count=1;
183: SPIEXCHANGE(count); // 发送MCP2510芯片,请求发送指令
184: WAIT_SPI();
185: return;
186: }
187: // 读取MCP2510芯片的状态
188: int GETS2510()
189: {
190: a[0]=STA2510;
191: a[1]=0;
192: count=2;
193: SPIEXCHANGE(count); // 读取MCP2510芯片状态
194: WAIT_SPI();
195: b[0]=a[1]; // 状态存到数组b[]中
196: return;
197: }
198: // 对MCP2510芯片进行位修改子程序
199: void BM2510(adress,mask,data)
200: int adress;
201: int mask;
202: int data;
203: {
204: a[0]=BITMOD; // 位修改指令
205: a[1]=adress; // 位修改寄存器地址
206: a[2]=mask; // 位修改屏蔽位
207: a[3]=data; // 位修改数据
208: count=4;
209: SPIEXCHANGE(count);
210: WAIT_SPI();
211: return;
212: }
213: // 设置MCP2510芯片为正常操作模式
214: void SETNORMAL()
215: {
216: int k=1;
217: BM2510(CANCTRL,0xe0,0x00); // 设置为正常操作模式
218: do {
219: RD2510(CANSTAT,1);
220: k=b[0]&0xe0;
221: }while(k); // 确认已进入正常操作模式
222: return;
223: }
224: // 对MCP2510进行初始化
225: void INIT2510()
226: {
227: RESET2510(); // 使芯片复位
228: b[0]=0x02;
229: b[1]=0x90;
230: b[2]=0x07;
231: WR2510(CNF3,3); // 波特率为 125 kbps
232: b[0]=0x00;
233: b[1]=0x00;
234: WR2510(RXM0SIDH,2);
235: b[0]=0x00;
236: b[1]=0x00;
237: WR2510(RXF0SIDH,2); // RX0接收,屏蔽位为0,过滤器为0
238: b[0]=0x00;
239: WR2510(CANINTE,1); // CAN中断不使能
240: SETNORMAL(); // 设置为正常操作模式
241: return;
242: }
243: // MCP2510芯片发送完成与否判断,邮箱号为adress
244: void TXCOMPLETE(adress)
245: int adress;
246: {
247: int k=1;
248: do {
249: RD2510(adress,1);
250: k=b[0]&0x08;
251: }while(k); // 确认是否已发送完毕 to add CLRWDT
252: return;
253: }
254: // 初始化PIC16F877芯片
255: void INIT877()
256: {
257: PORTA=0;
258: PORTB=0;
259: PORTC=0;
260: PORTD=0;
261: PORTE=0;
262: TRISA=0xff;
263: TRISB=0xfd;
264: TRISC=0xd7; // SCK, SDO:输出,SDI:输入
265: TRISD=0;
266: TRISE=0x03; // 片选CS信号输出
267: PORTA=0xff;
268: PORTB=0x03; // RST=1
269: PORTC=0;
270: PORTD=0xff;
271: PORTE=0x04;
272: return;
273: }
274: // 初始化SPI接口
275: void INITSPI()
276: {
277: SSPCON=0x11;
278: SSPEN=1; // SSP使能
279: SSPSTAT=0;
280: return;
281: }
282: // 发送数据子程序
283: void TXMSG(int DLC)
284: {
285: for(i=0;i<DLC;i++) b[i]=c[i];
286: WR2510(TXB0D0,DLC);
287: b[0]=DLC;
288: WR2510(TXB0DLC,1);
289: b[0]=0x03;
290: b[1]=RecID_H;
291: b[2]=RecID_L;
292: WR2510(TXB0CTRL,3);
293: RTS2510(0x01); // 请求发送
294: TXCOMPLETE(TXB0CTRL); //等待发送完毕
295: return;
296: }
297: // 接收数据子程序
298: int RXMSG()
299: {
300: int k;
301: RD2510(CANINTF,1);
302: k=b[0]&0x01;
303: if(k==1) {
304: BM2510(CANINTF,0x01,0x00);
305: RD2510(RXB0SIDH,2);
306: RecID_H=b[0];
307: RecID_L=b[1]&0xe0;
308: RD2510(RXB0DLC,1);
309: DLC=b[0]&0x0f;
310: RD2510(RXB0D0,DLC);
311: for(i=0;i<DLC;i++) c[i]=b[i];
312: return 1;
313: }
314: return 0;
315: }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -