找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2613|回复: 1
收起左侧

再次发帖 STC12 STC15 STC8单片机PCA_PWM频率可调1HZ步进 高精度

  [复制链接]
ID:254747 发表于 2021-9-16 22:03 | 显示全部楼层 |阅读模式
上次也发过类似的帖子  但是那个帖子 里面调节频率的时候  精度不是特别的高  现在修改了方法  精度还是可以的   
利用电位器调节    占空比也可以调节   这样方便驱动电动机 调节灯泡的亮度   

下面上图    有偶数HZ  奇数HZ  目的就是检查精度怎么样   

HZ数 请看数码管前两位即可 其它不用管  
1.jpg 1-1.jpg 13.jpg 13-1.jpg 18.jpg 18-1.jpg 24.jpg 24-1.jpg



下面是单片机程序   不对的地方 请大家指教
  1. #include <STC15F2K60S2.H>
  2. #include "intrins.h"

  3. //数码管延时
  4. void Delay100us()                //@24.000MHz
  5. {
  6.         unsigned char i, j;

  7.         i = 3;
  8.         j = 82;
  9.         do
  10.         {
  11.                 while (--j);
  12.         } while (--i);
  13. }


  14. #define ADC_POWER   0x80          //ADC电源控制位
  15. #define ADC_FLAG    0x10          //ADC完成标志
  16. #define ADC_START   0x08          //ADC起始控制位
  17. #define ADC_SPEEDLL 0x40          //180个时钟

  18. unsigned char ch2 = 0X02;         //通道选择变量 0x02;选择P1.2
  19. unsigned char ch3 = 0X03;         //选择P1.3
  20. unsigned char ch1 = 0X04;                                        //选择P1.4
  21. unsigned int  fupingjishu = 0;    //中断计数的


  22. unsigned char count();



  23. //void INT0_TEST();
  24. void ADC_INIT ();
  25. void PCA_REG_PWM();
  26. void PCA_PIN_LV_ADJ(unsigned char );
  27. void Timer0Init(void);
  28. void Timer1Init(void);


  29. unsigned int  ZHU_PIN_JIE_GUO_GetADCResult();
  30. unsigned char FU_PIN_JIE_GUO_GetADCResult();
  31. unsigned char ZHAN_KONG_BI_JIE_GUO_GetADCResult();


  32. void   JI_SHUAN();

  33. //连接138译码器  
  34. sbit   LSA = P5^1;   
  35. sbit   LSB = P5^2;
  36. sbit   LSC = P5^3;
  37. sbit   LED1 = P0^3;

  38. //0-9 数码段位显示数字
  39. unsigned  code   sumaguan_duan[10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};     

  40. //位选信号
  41. unsigned  char  displaydata[7] ;   
  42. void  shu_ma_guan();
  43. void  shumaguan_shuju_chuli(unsigned int zhupin,unsigned char fupin,unsigned char fupin_zhankongbi);


  44. main()
  45. {
  46.                  P5M0        =   0x00;   //0000,0000 端口5模式寄存器0
  47.      P5M1        =   0x00;   //0000,0000 端口5模式寄存器1
  48.      P4M0        =   0x00;   //0000,0000 端口4模式寄存器0  数码管用
  49.      P4M1        =   0x00;
  50.            P1M0        =   0x00;   //
  51.      P1M1       |=   0x1C;   //  设置P1.2为高阻输入模式
  52.            P0M0        =   0x00;   //0000,0000 端口4模式寄存器0  数码管用
  53.      P0M1        =   0x00;

  54.      ADC_INIT ();
  55.            PCA_REG_PWM();
  56.            Timer0Init();
  57. //           Timer1Init();

  58.     while (1)
  59.                 {


  60.                         

  61.                   shu_ma_guan();
  62.                   shumaguan_shuju_chuli(ZHU_PIN_JIE_GUO_GetADCResult(),FU_PIN_JIE_GUO_GetADCResult(),ZHAN_KONG_BI_JIE_GUO_GetADCResult());
  63.       PCA_PIN_LV_ADJ(FU_PIN_JIE_GUO_GetADCResult());     
  64.                         CCAP0H = CCAP0L = ZHAN_KONG_BI_JIE_GUO_GetADCResult();   
  65. //      JI_SHUAN();
  66.                         
  67.                         

  68.          
  69.                  }



  70. }



  71. // ADC初始化
  72. void ADC_INIT ()
  73.         
  74. {
  75.       P1ASF |= 0X1C;                       //  将P1.2 P1.3 P1.4 口作为ADC输入信号
  76.             ADC_RES=0;                           //清零转换结果寄存器高8位
  77.             ADC_RESL=0;                          //清零转换结果寄存器低2位
  78.       ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START ;

  79. }

  80. //高频结果转换  P1.2
  81. unsigned int ZHU_PIN_JIE_GUO_GetADCResult()
  82. {
  83.             unsigned int  zhupinjieguo;

  84.                   ADC_RES=0;                           //清零转换结果寄存器高8位
  85.             ADC_RESL=0;
  86.                         ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch1 | ADC_START;  //打开电源 速度180个时钟 选择通道2 启动转换
  87.                         _nop_();                             //等待4个NOP
  88.                         _nop_();
  89.                         _nop_();
  90.                         _nop_();
  91.                         while (!(ADC_CONTR & ADC_FLAG));     //等待ADC转换完成  全部为1 表示转换完成
  92.              ADC_CONTR &= ~0X80;                  //关闭ADC电源  节约功耗
  93.                         ADC_CONTR &= ~ADC_FLAG;              //Close ADC  清楚标识位
  94.                         zhupinjieguo =(ADC_RES<<2)+ADC_RESL; //将高2两位  和低8位的结果相加得到10位的结果

  95.       zhupinjieguo /= 4;                   //ad输出的结果最大是1024按照,但是只要0-300
  96.                                                  //缩小倍率就是1023除以300就是3.41 故用1023除以3.41即可转换为300
  97.             return zhupinjieguo;                 //返回ADC结果
  98. }
  99. //PCA_PWM_频率控制结果 P1.3
  100. unsigned char FU_PIN_JIE_GUO_GetADCResult()
  101. {
  102.             unsigned  int xdata fupingjieguo;
  103.                   ADC_RES=0;                           //清零转换结果寄存器高8位
  104.             ADC_RESL=0;
  105.            
  106.                         ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch2 | ADC_START;  //打开电源 速度180个时钟 选择通道2 启动转换
  107.                         _nop_();                             //等待4个NOP
  108.                         _nop_();
  109.                         _nop_();
  110.                         _nop_();
  111.                         while (!(ADC_CONTR & ADC_FLAG));     //等待ADC转换完成  全部为1 表示转换完成
  112.              ADC_CONTR &= ~0X80;                  //关闭ADC电源  节约功耗
  113.                         ADC_CONTR &= ~ADC_FLAG;              //Close ADC  清楚标识位
  114.                         fupingjieguo = (ADC_RES<<2)+ADC_RESL;    //将高2两位  和低8位的结果相加得到10位的结果

  115.             fupingjieguo /= 41;   //ad输出的结果最大是1024按照,但是只要0-25
  116.                                                  //缩小倍率就是1023除以25就是40.92 故用1023除以40.92即可转换为25

  117.             return fupingjieguo;                 //返回ADC结果
  118. }
  119. //PCA_PWM占空比结果  P1.4
  120. unsigned char ZHAN_KONG_BI_JIE_GUO_GetADCResult()
  121. {
  122.             unsigned int  zhankongbijieguo;
  123.             
  124.                   ADC_RES=0;                           //清零转换结果寄存器高8位
  125.             ADC_RESL=0;
  126.          
  127.                         ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch3 | ADC_START;  //打开电源 速度180个时钟 选择通道2 启动转换
  128.                         _nop_();                             //等待4个NOP
  129.                         _nop_();
  130.                         _nop_();
  131.                         _nop_();
  132.                         while (!(ADC_CONTR & ADC_FLAG));     //等待ADC转换完成  全部为1 表示转换完成
  133.              ADC_CONTR &= ~0X80;                  //关闭ADC电源  节约功耗
  134.                         ADC_CONTR &= ~ADC_FLAG;              //Close ADC  清楚标识位
  135.                         zhankongbijieguo =(ADC_RES<<2)+ADC_RESL;     //将高2两位  和低8位的结果相加得到10位的结果

  136.             zhankongbijieguo /= 4;       //ad输出的结果最大是1024按照,但是占空比只要0-98可调
  137.                                                             //缩小倍率就是1023除以100就是10.43 故用1023除以10.43即可转换为98

  138.             return zhankongbijieguo;                        //返回ADC结果
  139. }





  140. //数码管显示屏函数 初始化函数
  141. void  shu_ma_guan()
  142. {
  143.   unsigned  char xdata  i ,count;
  144.         count++;
  145.         if(count == 10)
  146.                  count = 0;

  147.                  for(i=0;i<7;i++)    //0 1 2 3 4 5 6
  148.                                  {
  149.                                                         switch(i)         //位选,选择点亮的数码管,
  150.                                                         {
  151.                                                                         case(0):
  152.                                                                                 LSA=0;LSB=0;LSC=0; break;//显示第0位
  153.                                                                         case(1):
  154.                                                                                 LSA=1;LSB=0;LSC=0; break;//显示第1位
  155.                                                                         case(2):
  156.                                                                                 LSA=0;LSB=1;LSC=0; break;//显示第2位
  157.                                                                         case(3):
  158.                                                                                 LSA=1;LSB=1;LSC=0; break;//显示第3位
  159.                                                                         case(4):
  160.                                                                                 LSA=0;LSB=0;LSC=1; break;//显示第4位
  161.                                                                         case(5):
  162.                                                                                 LSA=1;LSB=0;LSC=1; break;//显示第5位
  163.                                                                         case(6):
  164.                                                                                 LSA=0;LSB=1;LSC=1; break;//显示第6位
  165.                                                         }
  166.                                                                                                 
  167.                                                                          P4=displaydata[i];
  168.                                                                          Delay100us();
  169.                                                                          P4 = 0X00;   //消影信号
  170.                                  }


  171. }

  172. //数码管 数据接收与处理函数
  173. void  shumaguan_shuju_chuli(unsigned int zhupin,unsigned char fupin,unsigned char fupin_zhankongbi)
  174. {
  175. //       //低频频率
  176.                displaydata[0] = sumaguan_duan[fupin/10%10];
  177.                displaydata[1] = sumaguan_duan[fupin%10];
  178.             
  179.             
  180. //             //低频占空比
  181.                displaydata[2] = sumaguan_duan[fupin_zhankongbi/10%10];
  182.                displaydata[3] = sumaguan_duan[fupin_zhankongbi%10];
  183.         
  184.                                         //主频频率
  185.                                  displaydata[4] = sumaguan_duan[zhupin/100%10];
  186.                                  displaydata[5] = sumaguan_duan[zhupin/10%10];
  187.                                  displaydata[6] = sumaguan_duan[zhupin%10];
  188.         
  189. }

  190. //PCA_PWM寄存器配置
  191. void PCA_REG_PWM()
  192. {
  193.          
  194.      CMOD |=0X04;   //1、CPS2、CPS1、CPS0系统时钟,定时器0的溢出 脉冲
  195.                     //2、当CIDL=0时, 空闲模式下PCA计数器继续工作;
  196.                           //允许ECF溢出中断
  197.         
  198.      CCON &=0X00;   //不需要中断标志位和中断溢出所以并且初始化的时
  199.                     //候需要关闭PWM所以全部设置位0        
  200.         
  201.            CCAPM0 |=0X42; //允许比较器功能控制位  允许脉宽调节模式    P1.1
  202.                     //ECOM0:允许比较器功能控制位。 允许比较器
  203.                     //CAPP0: 正捕获控制位。        不允许
  204.                     //CAPN0:负捕获控制位。         不允许
  205.                                                                                 //MAT0: 匹配 控制位 。         不允许
  206.                                                                                 //TOG0: 翻转控制位。           不允许
  207.                                                                                 //PWM0: 脉宽调节模式           允许
  208.                                                                                 //ECCF0: 使能CCF0中断          不允许
  209.         
  210. //    CCAPM1 |=0X42; //同上                                      P1.0
  211.                  
  212.            CL = 0;        //低位初值设置为0
  213.            CH = 0;        //高位初值设置为0
  214.                  
  215.            CCAP0H = CCAP0L = 0x80;   //PWM    设置占空比为50%                              
  216.                                           
  217. //           CCAP1L = 0x80;   //PWM    设置占空比为50%                                   
  218. //           CCAP1H = 0x60;   //PWM    设置占空比为50%
  219.                  
  220.            PCA_PWM0 = 0X00; //PCA模块0工作于8位PWM功能
  221. //     PCA_PWM1 = 0X00; //PCA模块1工作于8位PWM功能                 
  222.      CR = 1 ;

  223. }




  224. ///*------------------------------------------
  225. //函数名:   定时器0
  226. //函数原型: void   Timer0Init(void)
  227. //所在文件: TIMER_DOC.c
  228. //功能描述: timer0定时的时间主要是给内部的
  229. //            PCA_PWM提供时钟频率
  230. //            请设置timer0为16位自动动重装  
  231. //            这样出来的频率精度高
  232. //输入参数: 无
  233. //返回:     无
  234. //作者:     Alan
  235. //时间:     2021年8月30日22:05:59

  236. //-------------------------------------------*/
  237. //定时器0溢出  设置PCA时钟用于调节频率
  238. void   Timer0Init(void)
  239. {

  240.         AUXR |= 0x80;                //定时器时钟1T模式
  241.         TMOD &= 0xF0;                //设置定时器模式
  242.         TL0 = 0xA0;                //设置定时初值
  243.         TH0 = 0xF6;                //设置定时初值
  244.         TF0 = 0;                //清除TF0标志
  245.         TR0 = 1;                //定时器0开始计时

  246. }


  247. //频率可调更新函数
  248. void PCA_PIN_LV_ADJ(unsigned char fuping)
  249. {
  250.         unsigned long  temp;

  251.         //重新初始化定时初值
  252.         temp = 0x10000-24000000/(fuping*256);
  253.         TH0 = temp>>8;                //设置定时初值
  254.         TL0 = temp;                  //设置定时初值


  255. }



  256. //void Timer1Init()                //1毫秒@24MHz
  257. //{
  258. //                        AUXR |= 0x40;                //定时器时钟1T模式
  259. //                        TMOD &= 0x0F;                //设置定时器模式
  260. //                        TL1 = 0x40;                  //设置定时初值
  261. //                        TH1 = 0xA2;                  //设置定时初值
  262. //                        TF1 = 0;                    //清除TF1标志
  263. //                        TR1 = 1;                    //定时器1开始计时
  264. //                        ET1 = 1;
  265. //                        EA = 1;
  266. //}


  267. //void tm1_isr() interrupt 3
  268. //{
  269. //          fupingjishu++;
  270. //}

  271. //void JI_SHUAN()
  272. //{
  273. //   
  274. //        unsigned char  temp;
  275. //        
  276. //        temp = 1000UL/ZHU_PIN_JIE_GUO_GetADCResult()/2;
  277. //         
  278. //         if(fupingjishu >= temp )
  279. //         {
  280. //                    fupingjishu = 0;
  281. //                     LED1 = ~LED1; //将测试口取反
  282. //         }

  283. //}





  284. 其实没有什么好深奥的地方  核心地方就是这里
  285. //频率可调更新函数
  286. void PCA_PIN_LV_ADJ(unsigned char fuping)
  287. {
  288.         unsigned long  temp;

  289.         //重新初始化定时初值
  290.         temp = 0x10000-24000000/(fuping*256);
  291.         TH0 = temp>>8;                //设置定时初值
  292.         TL0 = temp;                  //设置定时初值


  293. }
复制代码


24000000是晶振的频率   后面的fuping是你要多少HZ就填多少即可   最大值是有限制的   和你的晶振 还是定时器溢出的PCA时钟频率有关系 这个可以自己去调节  设置即可

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:230742 发表于 2021-9-19 23:59 | 显示全部楼层
好,太好了。感觉下载了学习学习PCA和PWM。感谢分享。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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