找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 19|回复: 1
打印 上一主题 下一主题
收起左侧

关于stc32g12k128-beta单片机自带can的ID过滤配置

[复制链接]
跳转到指定楼层
楼主
ID:1111967 发表于 2024-9-19 09:34 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
大家好,我最近刚接触stc32g系列单片机,听说这个单片机自带两个can口很方便,发的程序我试过了,通过外接一个收发器和官方给的例程可以精准的进行can的发送。但是我试了下滤单个id就是解决不了,请教一下大家该如何配置总线验收寄存器。我需要过滤单个id为10040901报文
  1. #include"STC32G.h"
  2. #include "intrins.h"

  3. typedef         unsigned char        u8;
  4. typedef         unsigned int        u16;
  5. typedef         unsigned long        u32;

  6. #define MAIN_Fosc        24000000UL

  7. /****************************** 用户定义宏 ***********************************/
  8. //CAN总线波特率=Fclk/((1+(TSG1+1)+(TSG2+1))*(BRP+1)*2)
  9. #define TSG1    2                //0~15
  10. #define TSG2    1                //1~7 (TSG2 不能设置为0)
  11. #define BRP     3                //0~63
  12. //24000000/((1+3+2)*4*2)=500KHz

  13. #define SJW     1                //重新同步跳跃宽度

  14. //总线波特率100KHz以上设置为 0; 100KHz以下设置为 1
  15. #define SAM     0                //总线电平采样次数: 0:采样1次; 1:采样3次

  16. /*****************************************************************************/


  17. /*************  本地常量声明    **************/

  18. #define Timer0_Reload   (65536UL -(MAIN_Fosc / 1000))       //Timer 0 中断频率, 1000次/秒

  19. #define        STANDARD_FRAME   0     //帧格式:标准帧
  20. #define        EXTENDED_FRAME   1     //帧格式:扩展帧

  21. /*************  本地变量声明    **************/

  22. typedef struct
  23. {
  24.         u8        DLC:4;          //数据长度, bit0~bit3
  25.         u8        :2;             //空数据, bit4~bit5
  26.         u8        RTR:1;          //帧类型, bit6
  27.         u8        FF:1;           //帧格式, bit7
  28.         u32        ID;             //CAN ID
  29.         u8        DataBuffer[8];  //数据缓存
  30. }CAN_DataDef;

  31. CAN_DataDef CAN1_Tx;
  32. CAN_DataDef CAN1_Rx[8];

  33. bit B_CanRead;      //CAN 收到数据标志
  34. bit B_1ms;          //1ms标志
  35. u16 msecond;

  36. /*************  本地函数声明    **************/
  37. void CANInit();
  38. u8 CanReadReg(u8 addr);
  39. u8 CanReadMsg(CAN_DataDef *CAN);
  40. void CanSendMsg(CAN_DataDef *CAN);

  41. void Delay1000ms(void)        //@24.000MHz
  42. {
  43.         unsigned long edata i;

  44.         _nop_();
  45.         _nop_();
  46.         i = 5999998UL;
  47.         while (i) i--;
  48. }

  49. /********************* 主函数 *************************/
  50. void main(void)
  51. {
  52.         u8 sr,i,n;
  53.                

  54.     WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
  55.     EAXFR = 1; //扩展寄存器(XFR)访问使能
  56.     CKCON = 0; //提高访问XRAM速度

  57.     P0M1 = 0x30;   P0M0 = 0x30;   //设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
  58.     P1M1 = 0x32;   P1M0 = 0x32;   //设置P1.1、P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V), P1.1在PWM当DAC电路通过电阻串联到P2.3
  59.     P2M1 = 0x3c;   P2M0 = 0x3c;   //设置P2.2~P2.5为漏极开路(实验箱加了上拉电阻到3.3V)
  60.     P3M1 = 0x50;   P3M0 = 0x50;   //设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
  61.     P4M1 = 0x3c;   P4M0 = 0x3c;   //设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
  62.     P5M1 = 0x0c;   P5M0 = 0x0c;   //设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
  63.     P6M1 = 0xff;   P6M0 = 0xff;   //设置为漏极开路(实验箱加了上拉电阻到3.3V)
  64.     P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口

  65.         AUXR = 0x80;    //Timer0 set as 1T, 16 bits timer auto-reload,
  66.         TH0 = (u8)(Timer0_Reload / 256);
  67.         TL0 = (u8)(Timer0_Reload % 256);
  68.         ET0 = 1;    //Timer0 interrupt enable
  69.         TR0 = 1;    //Tiner0 run

  70.         CANInit();
  71.         
  72.         EA = 1;                 //打开总中断

  73.         CAN1_Tx.FF = EXTENDED_FRAME;    //扩展帧
  74.         CAN1_Tx.RTR = 0;                //0:数据帧,1:远程帧
  75.         CAN1_Tx.DLC = 0x08;             //数据长度
  76.         CAN1_Tx.ID = 0x11040109;        //CAN ID
  77.         CAN1_Tx.DataBuffer[0] = 0x00;   //数据内容
  78.         CAN1_Tx.DataBuffer[1] = 0x00;
  79.         CAN1_Tx.DataBuffer[2] = 0x30;
  80.         CAN1_Tx.DataBuffer[3] = 0x00;
  81.         CAN1_Tx.DataBuffer[4] = 0x00;
  82.         CAN1_Tx.DataBuffer[5] = 0x00;
  83.         CAN1_Tx.DataBuffer[6] = 0x80;
  84.         CAN1_Tx.DataBuffer[7] = 0x00;
  85.                 P54 = 0;
  86.         Delay1000ms();
  87.         P54 = 1;
  88.         while(1)
  89.         {
  90.                 if(B_1ms)   //1ms到
  91.                 {
  92.                         B_1ms = 0;
  93.                         if(++msecond >= 1000)   //1秒到
  94.                         {
  95.                                 msecond = 0;
  96.                                 sr = CanReadReg(SR);

  97.                                 if(sr & 0x01)                //判断是否有 BS:BUS-OFF状态
  98.                                 {
  99.                                         CANAR = MR;
  100.                                         CANDR &= ~0x04;  //清除 Reset Mode, 从BUS-OFF状态退出
  101.                                 }
  102.                                 else
  103.                                 {
  104.                     CanSendMsg(&CAN1_Tx);   //发送一帧数据
  105.                                 }
  106.                         }
  107.                 }

  108.                 if(B_CanRead)
  109.                 {
  110.                         B_CanRead = 0;
  111.                         
  112.             n = CanReadMsg(CAN1_Rx);    //读取接收内容
  113.             if(n>0)
  114.             {
  115.                 for(i=0;i<n;i++)
  116.                 {
  117.                     CanSendMsg(&CAN1_Rx[i]);  //CAN总线原样返回
  118.                 }
  119.             }
  120.                 }
  121.         }
  122. }


  123. /********************** Timer0 1ms中断函数 ************************/
  124. void timer0 (void) interrupt 1
  125. {
  126.     B_1ms = 1;      //1ms标志
  127. }

  128. //========================================================================
  129. // 函数: u8 ReadReg(u8 addr)
  130. // 描述: CAN功能寄存器读取函数。
  131. // 参数: CAN功能寄存器地址.
  132. // 返回: CAN功能寄存器数据.
  133. // 版本: VER1.0
  134. // 日期: 2020-11-16
  135. // 备注:
  136. //========================================================================
  137. u8 CanReadReg(u8 addr)
  138. {
  139.         u8 dat;
  140.         CANAR = addr;
  141.         dat = CANDR;
  142.         return dat;
  143. }

  144. //========================================================================
  145. // 函数: void WriteReg(u8 addr, u8 dat)
  146. // 描述: CAN功能寄存器配置函数。
  147. // 参数: CAN功能寄存器地址, CAN功能寄存器数据.
  148. // 返回: none.
  149. // 版本: VER1.0
  150. // 日期: 2020-11-16
  151. // 备注:
  152. //========================================================================
  153. void CanWriteReg(u8 addr, u8 dat)
  154. {
  155.         CANAR = addr;
  156.         CANDR = dat;
  157. }

  158. //========================================================================
  159. // 函数: void CanReadFifo(CAN_DataDef *CANx)
  160. // 描述: 读取CAN缓冲区数据函数。
  161. // 参数: *CANx: 存放CAN总线读取数据.
  162. // 返回: none.
  163. // 版本: VER2.0
  164. // 日期: 2023-01-31
  165. // 备注:
  166. //========================================================================
  167. void CanReadFifo(CAN_DataDef *CAN)
  168. {
  169.     u8 i;
  170.     u8 pdat[5];
  171.     u8 RX_Index=0;

  172.     pdat[0] = CanReadReg((u8)(RX_BUF0 + (RX_Index++&3)));

  173.     if(pdat[0] & 0x80)  //判断是标准帧还是扩展帧
  174.     {
  175.         pdat[1] = CanReadReg((u8)(RX_BUF0 + (RX_Index++&3)));   //扩展帧ID占4个字节
  176.         pdat[2] = CanReadReg((u8)(RX_BUF0 + (RX_Index++&3)));
  177.         pdat[3] = CanReadReg((u8)(RX_BUF0 + (RX_Index++&3)));
  178.         pdat[4] = CanReadReg((u8)(RX_BUF0 + (RX_Index++&3)));
  179.         CAN->ID = (((u32)pdat[1] << 24) + ((u32)pdat[2] << 16) + ((u32)pdat[3] << 8) + pdat[4]) >> 3;
  180.     }
  181.     else
  182.     {
  183.         pdat[1] = CanReadReg((u8)(RX_BUF0 + (RX_Index++&3)));   //标准帧ID占2个字节
  184.         pdat[2] = CanReadReg((u8)(RX_BUF0 + (RX_Index++&3)));
  185.         CAN->ID = ((pdat[1] << 8) + pdat[2]) >> 5;
  186.     }

  187.     CAN->FF = pdat[0] >> 7;     //帧格式
  188.     CAN->RTR = pdat[0] >> 6;    //帧类型
  189.     CAN->DLC = pdat[0];         //数据长度

  190.     for(i=0;((i<CAN->DLC) && (i<8));i++)        //读取数据长度为len,最多不超过8
  191.     {
  192.         CAN->DataBuffer[i] = CanReadReg((u8)(RX_BUF0 + (RX_Index++&3)));   //读取有效数据
  193.     }
  194.     while(RX_Index&3)   //判断已读数据长度是否4的整数倍
  195.     {
  196.         CanReadReg((u8)(RX_BUF0 + (RX_Index++&3)));  //读取填充数据,一帧数据占据4的整数倍缓冲区空间,不足补0
  197.     }
  198. }

  199. //========================================================================
  200. // 函数: u8 CanReadMsg(void)
  201. // 描述: CAN接收数据函数。
  202. // 参数: *CANx: 存放CAN总线读取数据..
  203. // 返回: 帧个数.
  204. // 版本: VER2.0
  205. // 日期: 2023-01-31
  206. // 备注:
  207. //========================================================================
  208. u8 CanReadMsg(CAN_DataDef *CAN)
  209. {
  210.     u8 i;
  211.     u8 n=0;

  212.     do{
  213.         CanReadFifo(&CAN[n++]);  //读取接收缓冲区数据
  214.         i = CanReadReg(SR);
  215.     }while(i&0x80);     //判断接收缓冲区里是否还有数据,有的话继续读取

  216.     return n;   //返回帧个数
  217. }

  218. //========================================================================
  219. // 函数: void CanSendMsg(CAN_DataDef *CAN)
  220. // 描述: CAN发送标准帧函数。
  221. // 参数: *CANx: 存放CAN总线发送数据..
  222. // 返回: none.
  223. // 版本: VER1.0
  224. // 日期: 2020-11-19
  225. // 备注:
  226. //========================================================================
  227. void CanSendMsg(CAN_DataDef *CAN)
  228. {
  229.         u32 CanID;
  230.     u8 RX_Index,i;

  231.     if(CAN->FF)     //判断是否扩展帧
  232.     {
  233.         CanID = CAN->ID << 3;
  234.         CanWriteReg(TX_BUF0,CAN->DLC|((u8)CAN->RTR<<6)|0x80);        //bit7: 标准帧(0)/扩展帧(1), bit6: 数据帧(0)/远程帧(1), bit3~bit0: 数据长度(DLC)
  235.         CanWriteReg(TX_BUF1,(u8)(CanID>>24));
  236.         CanWriteReg(TX_BUF2,(u8)(CanID>>16));
  237.         CanWriteReg(TX_BUF3,(u8)(CanID>>8));

  238.         CanWriteReg(TX_BUF0,(u8)CanID);

  239.         RX_Index = 1;
  240.         for(i=0;((i<CAN->DLC) && (i<8));i++)        //数据长度为DLC,最多不超过8
  241.         {
  242.             CanWriteReg((u8)(TX_BUF0 + (RX_Index++&3)),CAN->DataBuffer[i]);   //写入有效数据
  243.         }
  244.         while(RX_Index&3)   //判断已读数据长度是否4的整数倍
  245.         {
  246.             CanWriteReg((u8)(TX_BUF0 + (RX_Index++&3)),0x00);  //写入填充数据,一帧数据占据4的整数倍缓冲区空间,不足补0
  247.         }
  248.     }
  249.     else    //发送标准帧
  250.     {
  251.         CanID = (u16)(CAN->ID << 5);
  252.         CanWriteReg(TX_BUF0,CAN->DLC|((u8)CAN->RTR<<6));  //bit7: 标准帧(0)/扩展帧(1), bit6: 数据帧(0)/远程帧(1), bit3~bit0: 数据长度(DLC)
  253.         CanWriteReg(TX_BUF1,(u8)(CanID>>8));
  254.         CanWriteReg(TX_BUF2,(u8)CanID);

  255.         RX_Index = 3;
  256.         for(i=0;((i<CAN->DLC) && (i<8));i++)        //数据长度为DLC,最多不超过8
  257.         {
  258.             CanWriteReg((u8)(TX_BUF0 + (RX_Index++&3)),CAN->DataBuffer[i]);   //写入有效数据
  259.         }
  260.         while(RX_Index&3)   //判断已读数据长度是否4的整数倍
  261.         {
  262.             CanWriteReg((u8)(TX_BUF0 + (RX_Index++&3)),0x00);  //写入填充数据,一帧数据占据4的整数倍缓冲区空间,不足补0
  263.         }
  264.     }
  265.         CanWriteReg(CMR ,0x04);                //发起一次帧传输
  266. }

  267. //========================================================================
  268. // 函数: void CANSetBaudrate()
  269. // 描述: CAN总线波特率设置函数。
  270. // 参数: none.
  271. // 返回: none.
  272. // 版本: VER1.0
  273. // 日期: 2020-11-19
  274. // 备注:
  275. //========================================================================
  276. void CANSetBaudrate()
  277. {
  278.         CanWriteReg(BTR0,(SJW << 6) + BRP);
  279.         CanWriteReg(BTR1,(SAM << 7) + (TSG2 << 4) + TSG1);
  280. }

  281. //========================================================================
  282. // 函数: void CANInit()
  283. // 描述: CAN初始化函数。
  284. // 参数: none.
  285. // 返回: none.
  286. // 版本: VER1.0
  287. // 日期: 2020-11-19
  288. // 备注:
  289. //========================================================================
  290. void CANInit()
  291. {
  292.         CANEN = 1;          //CAN1模块使能
  293.         CanWriteReg(MR  ,0x05);  //使能 Reset Mode, 采用单滤波设置

  294.         CANSetBaudrate();        //设置波特率
  295.         
  296.         //设置过滤ID为:xxF8xxxx 的帧才接收
  297.         CanWriteReg(ACR0,0x80);                //总线验收代码寄存器
  298.         CanWriteReg(ACR1,0x20);
  299.         CanWriteReg(ACR2,0x48);
  300.         CanWriteReg(ACR3,0x08);
  301.         CanWriteReg(AMR0,0x80);                //总线验收屏蔽寄存器
  302.         CanWriteReg(AMR1,0x20);
  303.         CanWriteReg(AMR2,0x48);
  304.         CanWriteReg(AMR3,0x08);

  305.         //取消过滤ID,所有帧都接收
  306. //        CanWriteReg(ACR0,0x00);                //总线验收代码寄存器
  307. //        CanWriteReg(ACR1,0x00);
  308. //        CanWriteReg(ACR2,0x00);
  309. //        CanWriteReg(ACR3,0x00);
  310. //        CanWriteReg(AMR0,0xFF);                //总线验收屏蔽寄存器
  311. //        CanWriteReg(AMR1,0xFF);
  312. //        CanWriteReg(AMR2,0xFF);
  313. //        CanWriteReg(AMR3,0xFF);

  314.         CanWriteReg(IMR ,0xff);                //中断寄存器
  315.         CanWriteReg(ISR ,0xff);                //清中断标志
  316.         CanWriteReg(MR  ,0x01);                //退出 Reset Mode, 采用单滤波设置(设置过滤器后注意选择滤波模式)
  317. //        CanWriteReg(MR  ,0x00);                //退出 Reset Mode, 采用双滤波设置(设置过滤器后注意选择滤波模式)

  318.         P_SW1 = (P_SW1 & ~(3<<4)) | (0<<4); //端口切换(CAN_Rx,CAN_Tx) 0x00:P0.0,P0.1  0x10:P5.0,P5.1  0x20:P4.2,P4.5  0x30:P7.0,P7.1
  319.         CANICR = 0x02;                //CAN中断使能
  320. }

  321. //========================================================================
  322. // 函数: void CANBUS_Interrupt(void) interrupt CAN1_VECTOR
  323. // 描述: CAN总线中断函数。
  324. // 参数: none.
  325. // 返回: none.
  326. // 版本: VER1.0
  327. // 日期: 2020-11-19
  328. // 备注:
  329. //========================================================================
  330. void CANBUS_Interrupt(void) interrupt CAN1_VECTOR
  331. {
  332.         u8 isr;
  333.         u8 arTemp;
  334.         arTemp = CANAR;     //CANAR现场保存,避免主循环里写完 CANAR 后产生中断,在中断里修改了 CANAR 内容
  335.         
  336.         isr = CanReadReg(ISR);
  337.         if((isr & 0x04) == 0x04)  //TI
  338.     {
  339.                 CANAR = ISR;
  340.                 CANDR = 0x04;    //CLR FLAG
  341.     }        
  342.         if((isr & 0x08) == 0x08)  //RI
  343.     {
  344.                 CANAR = ISR;
  345.                 CANDR = 0x08;    //CLR FLAG
  346.         
  347.                 B_CanRead = 1;
  348.     }

  349.         if((isr & 0x40) == 0x40)  //ALI
  350.     {
  351.                 CANAR = ISR;
  352.                 CANDR = 0x40;    //CLR FLAG
  353.     }        

  354.         if((isr & 0x20) == 0x20)  //EWI
  355.     {
  356.                 CANAR = ISR;
  357.                 CANDR = 0x20;    //CLR FLAG
  358.     }        

  359.         if((isr & 0x10) == 0x10)  //EPI
  360.     {
  361.                 CANAR = ISR;
  362.                 CANDR = 0x10;    //CLR FLAG
  363.     }        

  364.         if((isr & 0x02) == 0x02)  //BEI
  365.     {
  366.                 CANAR = ISR;
  367.                 CANDR = 0x02;    //CLR FLAG
  368.     }        

  369.         if((isr & 0x01) == 0x01)  //DOI
  370.     {
  371.                 CANAR = ISR;
  372.                 CANDR = 0x01;    //CLR FLAG
  373.     }        

  374.         CANAR = arTemp;    //CANAR现场恢复
  375. }
复制代码


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:314246 发表于 2024-9-19 11:57 | 只看该作者
手册上有说明,这个是可以过滤的,我用过

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表