切换到宽版
爱科技/爱创意/爱折腾/爱极致;技术知识分享平台,点击进入新版数码之家网站
  • 2441阅读
  • 8回复

[其他]零基础学习STM8开发笔记(三) [复制链接]

上一主题 下一主题
离线fox69
 

发帖
176
M币
1174
专家
7
粉丝
29
只看楼主 倒序阅读 我要置顶 楼主  发表于: 2017-07-28
  接上篇笔记:http://bbs.mydigit.cn/read.php?tid=2176066
  我们的最终目的是控制IO端口发出PWM信号,即脉冲宽度可自由变化的方波信号,本篇就来实现它。
  先用PWM的方法替代上篇的中断方法:

#include<intrinsics.h>
#include<iostm8s103f3.h>

int main()
{
   TIM2_PSCR =11;         // Timer2的预分频2048

   TIM2_ARRH =0x03;        // Timer2的自动重载寄存器高位
   TIM2_ARRL =0xD0;       // Timer2的自动重载寄存器低位    两个合起来是 976

   TIM2_CCR2H =0x2;        // 低电平保持时间
   TIM2_CCR2L =0x58;

  TIM2_CCER1_CC2P = 1;     // lowlevel
  TIM2_CCER1_CC2E = 1;     // OC2

  TIM2_CCMR2_OC2PE = 1;    // 通道2预装载使能
  TIM2_CCMR2_OC2M = 0x6;   //110  PWM模式1

   TIM2_CR1_CEN =1;    // 启动定时器2

   while(1)
   {
     __no_operation(); // 空操作可以用 asm("nop"); 代替
   }
}

  程序解释:
  这里我们使用了定时器2,没有使用定时器1,因为之后还有其他用处。TIM2_PSCR是定时器2的预分频寄存器,但与定时器1不同,它只使用了4位,分频数只有16种,实际分频值是2的幂次,如11是2的11次幂,分频值就是2048。设置TIM2_ARR(Timer2一周期计数次数)为0x3D0(十进制的976),与2048相乘接近2000000,将2MHz按此数进行计数,得到一个计数周期是1秒。
  TIM2_CCMR2_OC2M = 0x6; 这一句将Timer2的通道2设置成PWM模式1。
  TIM2_CCMR2_OC2PE = 1;    这一句使TIM2的通道2能连续工作。
  因为PWM功能使用了定时器的输入/捕获功能,所以设置:
  TIM2_CCER1_CC2P = 1;    TIM2的通道2低电平有效,
  TIM2_CCER1_CC2E = 1;    TIM2的通道2作为输出,TIM2产生的PWM脉冲将从TIM2的通道2输出。
  TIM2_CCR2 决定了PWM脉冲的占空比,因为TIM2_ARR的值为976,所以它的取值可以从0到976(大于也可以)。这里取了整个周期的2/3左右。
  最后用TIM2_CR1_CEN= 1 启动定时器2。



  看一下上图,PD3复用为TIM2_CH2,正是Timer2的第二通道,所以定时器2启动后,D3口2/3时间保持低电平,LED亮,1/3时间为高电平,LED灭。由于核心板的LED在B5上,我们用导线将D3与B5联通,B5端口未进行设置,所以它保持输入的高阻状态,等于由D3接管了LED。




  PWM信号周期是1秒,控制了LED的闪烁,我们的目的是用PWM实现LED亮度控制,为此可提高PWM频率,到1000Hz,人眼就观察不到闪烁,调整占空比就改变了亮度。
  修改一下前三句:
  TIM2_PSCR =0;          // Timer2的预分频1
  TIM2_ARRH =0x07;        // Timer2的自动重载寄存器高位
  TIM2_ARRL =0xD0;        // Timer2的自动重载寄存器低位    两个合起来是 2000
  TIM2不再进行预分频,计数周期改为2000次,2MHz的主机脉冲导致定时器计数频率为1KHz。
  运行后LED连续发光,亮度比之前降低了。

  试改变TIM2_CCR2的值,调整占空比:












LED亮度随着改变。

更进一步,做一个亮度渐亮渐暗的呼吸灯。代码:


#include<intrinsics.h>
#include<iostm8s103f3.h>

int level = 0;  
int inc = 1;

int main()
{
   TIM2_PSCR = 0;          // Timer2的预分频1

   TIM2_ARRH = 0x07;        // Timer2的自动重载寄存器高位
   TIM2_ARRL = 0xD0;        // Timer2的自动重载寄存器低位    两个合起来是 2000

   TIM2_CCR2H = 0x2;        // 低电平保持时间
   TIM2_CCR2L = 0x58;

   TIM2_CCER1_CC2P = 1;     // low level
   TIM2_CCER1_CC2E = 1;     // OC2

   TIM2_CCMR2_OC2PE = 1;    // 通道2预装载使能
   TIM2_CCMR2_OC2M = 0x6;   //110 PWM模式1

   TIM2_CR1_CEN = 1;    // 启动定时器2

   TIM1_PSCRH = 0x03;       // Timer1的预分频寄存器值高位, 与低位合起来值是999,即Timer1的输入时钟分频1000
   TIM1_PSCRL = 0xE7;       // Timer1第预分频寄存器值低位

   TIM1_ARRH = 0x0;       // Timer1的自动重载寄存器高位
   TIM1_ARRL = 0x20;        // Timer1的自动重载寄存器低位  

   TIM1_IER_UIE = 1;       // 设置Timer1中断允许

   TIM1_CR1_ARPE = 1;       // 设置Timer1为自动重载模式
   TIM1_CR1_CEN = 1;        // 设置Timer1启动计时

   __enable_interrupt();    // 开系统中断  可用  asm("rim"); 代替

   while(1)
   {
      __no_operation(); // 空操作 可以用 asm("nop"); 代替
   }
}

#pragma vector =TIM1_OVR_UIF_vector    //设置Timer1的中断向量地址,其值为 0xD  
__interrupt voidTIM1_IRQ(void)         // Timer1 的中断程序
{
    TIM1_SR1_UIF = 0;
    level += inc;
    if(level >= 100) inc = -1;
    else if(level <= 0) inc = 1;

    int CCR2 = 20 * level;   // 0 - 2000, 亮度变化100级

    TIM2_CCR2H = (CCR2 >> 8);        // 低电平保持时间
    TIM2_CCR2L = CCR2 & 0xFF;
}

  与上篇类似,我们又使用了定时器1,每隔一定时间产生中断,全局变量level决定亮度级别,从0到100来回变化。在中断处理过程中,当level大于0时inc为+1,level +=inc使level每次增量1,达到100后,inc = -1,level +=inc使level每次减1,减到0时inc = 1。
局部16位变量CCR2 =20 * level,其值变化范围为0-2000,符合定时器2的计数周期范围。
  语句:
  TIM2_CCR2H = (CCR2 >> 8);        // CCR2右移8位,取出CCR2高8位
  TIM2_CCR2L = CCR2 & 0xFF;      // 取CCR2低8位
  将CCR2拆分为高、低8位分别赋值给占空比控制寄存器TIM2_CCR2的高8位和低8位。

  运行后LED变成了呼吸灯。
  STM8的定时器比较复杂,我只是使用了极少的功能,也是反复把手册的这部分前后看了若干遍,第一遍看的时候不明白的概念比较多,看下来一头雾水,不过初学就这样,不能轻易放弃,看一遍再通过实践试错就能弄懂一两个概念,再回头看难度就减少一些,又能弄懂一两个概念,如此反复迭代多次低手就能变成高手了。

  待续…下一篇:http://bbs.mydigit.cn/read.php?tid=2177114&ds=1
[ 此帖被fox69在2017-07-29 16:16重新编辑 ]
本文内容包含图片或附件,获取更多资讯,请 登录 后查看;或者 注册 成为会员获得更多权限
本帖最近打赏记录:共4条打赏M币+32
离线goyimen

发帖
1337
M币
1401
专家
3
粉丝
33
只看该作者 1楼 发表于: 2017-07-28
请登录后查看
离线rogerllg

发帖
6106
M币
10576
专家
5
粉丝
73
只看该作者 2楼 发表于: 2017-07-28
请登录后查看
离线2545889167

发帖
13268
M币
20754
专家
302
粉丝
4860
只看该作者 3楼 发表于: 2017-07-28
请登录后查看
离线dzljp

发帖
7351
M币
16345
专家
4
粉丝
27
只看该作者 4楼 发表于: 2017-07-28
请登录后查看
离线965039114

发帖
6143
M币
36775
专家
115
粉丝
367
只看该作者 5楼 发表于: 2017-07-28
请登录后查看
离线tnc100

发帖
15
M币
0
专家
0
粉丝
1
只看该作者 6楼 发表于: 2017-07-28
请登录后查看
离线zeze10000

发帖
2858
M币
8559
专家
35
粉丝
112
只看该作者 7楼 发表于: 2017-07-28
请登录后查看
离线wlhcq
发帖
31
M币
-479
专家
0
粉丝
4
只看该作者 8楼 发表于: 2017-07-29
请登录后查看
快速回复
限80 字节
如果您提交过一次失败了,可以用”恢复数据”来恢复帖子内容
 
上一个 下一个