[PIC®/AVR®/dsPIC®产品] 如何启用PIC18的扩展指令集?

[复制链接]
panxiaoyi 发表于 2021-4-23 12:10 来自手机 | 显示全部楼层
我上面的如果有错,估计就是cpu时钟问题,中断和中断时间和中断所消耗的震荡时钟应该是正确的,经过了秒表测试求平均值的
panxiaoyi 发表于 2021-4-23 12:15 来自手机 | 显示全部楼层
AVR比较简单,放假回去我也让ATmega48跑一遍试试,现在手头没有工具
panxiaoyi 发表于 2021-4-24 10:35 | 显示全部楼层
代码做了微调,没有使用系统生成的配置字,芯片使用 PIC18F26K83
panxiaoyi 发表于 2021-4-24 10:36 | 显示全部楼层
  1. //PIC18F26K83
  2. //配置字关闭了外部振荡器,启用内部64M时钟,其它的默认
  3. //看门狗默认开启,使用内部31K时钟定时2s

  4. //#include "Configuration.h"
  5. #pragma config CONFIG1L=0b00000100            //配置字设置:时钟=内部64M,分频=1,外部振荡器关闭

  6. #include <xc.h>

  7. #include "BIT.h"
  8. #include "DELAY_LONG.h"
  9. #include "FONT0805.h"
  10. #include "MCUIIC.h"
  11. #include "SH1106.h"

  12. #define out LATB

  13. unsigned int ii, nn;
  14. unsigned char xx, aa;

  15. unsigned char test(unsigned char dat)
  16. {
  17.     unsigned char yy;
  18.     yy=dat;
  19.     return yy;
  20. }

  21. void __interrupt(irq(TMR0),high_priority) myTmrIsr(void)       //增强型PIC18有很多个中断向量
  22. {
  23.     nn++;
  24.     LATC1=1;                                  //LED亮
  25.     __asm("CLRWDT");                          //清狗
  26.     TMR0IF=0;                                 //清零中断标记
  27.     OLED_gotoxy(71,3);                        //显示时间
  28.     OLED_show(nn);
  29.     LATC1=0;
  30.     if(aa)                                    //显示:程序在1600K个CPU时钟里运行for()语句的次数
  31.     {
  32.         aa=0;
  33.         OLED_gotoxy(35,3);
  34.         OLED_show(ii);
  35.     }
  36. }

  37. void main(void)
  38. {
  39.     OSCCON1=0b01100000;                       //高4位是时钟选择,本例选择高频内部时钟HFINTOSC,低4位是“后”分配器选择,0000=1分频
  40.     OSCFRQ=8;                                 //高频内部时钟HFINTOSC的频率选择,=8就是64MHz
  41.     WDTCON1=7;                                //看门狗溢出时间=65536/31K=2s,窗口期100%,窗口期就是说什么时候可以清狗,什么时候清狗属于违规
  42.    
  43.     IIC_init();
  44.     OLED_init();
  45.     OLED_clear();
  46.     OLED_gotoxy(11,1);
  47.     OLED_string("PIC18F26K83>SH1106");
  48.     OLED_gotoxy(11,5);
  49.     OLED_string("21IC.COM PANXIAOYI");
  50.    
  51.     TRISC1=0;                                 //输出驱动LED,测试T0计数溢出中断
  52.     TRISC2=0;                                 //输出驱动LED,测试T0输出,LED不会闪烁,不正常
  53.     RC2PPS=0x25;                              //某端口定义为由计数器TMR0计数溢出输出驱动电平翻转

  54.    
  55.     TMR0H=195;

  56.     TMR0IP=1;                                 //高级中断
  57.     TMR0IE=1;                                 //中断允许
  58.     ei();                                     //总中断使能
  59.    
  60.     T0CON1 B6H;                               //Fosc/4=16M时钟
  61.     T0CON1 B3H;                               //预分频8192
  62.     T0CON1 B2H;
  63.     T0CON1 B1L;
  64.     T0CON1 B0H;
  65.     T0CON0 B4L;                               //使用8位模式
  66.     T0CON0 B7H;                               //启动计时器
  67.    
  68.    
  69.     aa=1;
  70.     ii=1;
  71.     nn=0;
  72.     while(1)
  73.     {
  74.         for(ii=0; ii<65535; ii++)             //全部语句可以运行8988次
  75.         {
  76.             xx=test(37);                      //注释这条可以运行9580次
  77.             out=xx;
  78.             
  79.             if(xx>47) xx=57; else xx=67;      //注释这条可以运行9998次
  80.             out=xx;
  81.             
  82.             xx<<=1;                           //注释这条可以运行9248次
  83.             out=xx;
  84.             
  85.             xx>>=1;                           //注释这条可以运行9248次
  86.             out=xx;
  87.             
  88.             xx|=1;                            //注释这条可以运行9142次
  89.             out=xx;
  90.             
  91.             xx&=1;                            //注释这条可以运行9142次
  92.             out=xx;
  93.             
  94.             xx=~xx;                            //注释这条可以运行9142次
  95.             out=xx;
  96.             
  97.             xx=xx^1;                           //注释这条可以运行9142次
  98.             out=xx;
  99.             
  100.             xx+=1;                            //注释这条可以运行9090次
  101.             out=xx;
  102.             
  103.             xx-=1;                            //注释这条可以运行9090次
  104.             out=xx;
  105.             
  106.             xx*=3;                            //注释这条可以运行9523次
  107.             out=xx;
  108.             
  109.             xx/=3;                            //注释这条可以运行9523次
  110.             out=xx;
  111.             
  112.             xx%=3;                            //注释这条可以运行9638次
  113.             out=xx;
  114.         }
  115.         while(1);
  116.     }
  117. }

代码如下:
panxiaoyi 发表于 2021-4-24 10:45 | 显示全部楼层
上面的代码中,修改47行的“后”分频,和48行的频率选择,显示器的速度都有不同反应,但是,运行for语句不变,只有1655次
我认为我上面的时钟没有选错,系统时钟就是 64M ,后分频就是 1 ,就是没有分频,看来 PIC 的速度就是这么慢了,1T的51可以运行9000次,PIC只运行了1655次
如果大家看出了哪里有错,也多谢指正


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
panxiaoyi 发表于 2021-4-24 10:46 | 显示全部楼层
完整代码如下

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
panxiaoyi 发表于 2021-4-24 10:53 | 显示全部楼层
每秒中断次数 = 64M 除以 4分频 ,再除以 8192 分频 ,再除以 195 计数 ,= 10 次/s
systemchip 发表于 2021-4-25 10:41 | 显示全部楼层

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
panxiaoyi 发表于 2021-4-30 12:10 | 显示全部楼层
AVR 的 ATmega48 使用 CodeVisionAVR V2.05.0
HC89F0541 使用 Keil C51 9.60A
PIC 使用 MPLAB X IDE v4.20 加 xc8 Free V2.32
全部都是默认优化,业余爱好测试,结果如图




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
慢动作 发表于 2021-4-30 21:55 | 显示全部楼层
看看优化之后的。
慢动作 发表于 2021-4-30 21:58 | 显示全部楼层
panxiaoyi 发表于 2021-4-23 12:15
AVR比较简单,放假回去我也让ATmega48跑一遍试试,现在手头没有工具

重新做了吗?
panxiaoyi 发表于 2021-4-30 22:50 | 显示全部楼层
上面的截图就是结果啊,因为ATmega48使用的是1M时钟,因此结果 159 要 乘以16, 16*159=2544次,就是说如果是16M时钟的话,它的运行结果就是2544次,其它的类推。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 在线客服 返回列表 返回顶部