STM8例程—音乐播放(使用定时器PWM)

合集下载

stm8笔记2-定时3更新中断+pwm输出(IDE为IAR)

stm8笔记2-定时3更新中断+pwm输出(IDE为IAR)

stm8笔记2-定时3更新中断+pwm输出(IDE为IAR)⼀:IAR编译器中断函数说明下⾯说⼀下在IAR下,在IAR下必须要添加iostm8s105s6.h⽂件,在⽂件的最后有如下内容:/*-------------------------------------------------------------------------* Interrupt vector numbers*-----------------------------------------------------------------------*/#define AWU_vector 0x03#define SPI_TXE_vector 0x0C#define SPI_RXNE_vector 0x0C#define SPI_WKUP_vector 0x0C#define SPI_CRCERR_vector 0x0C#define SPI_OVR_vector 0x0C#define SPI_MODF_vector 0x0C#define TIM1_OVR_UIF_vector 0x0D#define TIM1_CAPCOM_BIF_vector 0x0D#define TIM1_CAPCOM_TIF_vector 0x0D#define TIM1_CAPCOM_CC1IF_vector 0x0E#define TIM1_CAPCOM_CC2IF_vector 0x0E#define TIM1_CAPCOM_CC3IF_vector 0x0E#define TIM1_CAPCOM_CC4IF_vector 0x0E#define TIM1_CAPCOM_COMIF_vector 0x0E#define TIM2_OVR_UIF_vector 0x0F#define TIM2_CAPCOM_CC1IF_vector 0x10#define TIM2_CAPCOM_TIF_vector 0x10#define TIM2_CAPCOM_CC2IF_vector 0x10#define TIM2_CAPCOM_CC3IF_vector 0x10#define UART1_T_TXE_vector 0x13#define UART1_T_TC_vector 0x13#define UART1_R_OR_vector 0x14#define UART1_R_RXNE_vector 0x14#define UART1_R_IDLE_vector 0x14#define UART1_R_PE_vector 0x14#define UART1_R_LBDF_vector 0x14#define I2C_ADD10_vector 0x15#define I2C_ADDR_vector 0x15#define I2C_OVR_vector 0x15#define I2C_STOPF_vector 0x15#define I2C_BTF_vector 0x15#define I2C_WUFH_vector 0x15#define I2C_RXNE_vector 0x15#define I2C_TXE_vector 0x15#define I2C_BERR_vector 0x15#define I2C_ARLO_vector 0x15#define I2C_AF_vector 0x15#define I2C_SB_vector 0x15#define ADC1_AWS0_vector 0x18#define ADC1_AWS1_vector 0x18#define ADC1_AWS2_vector 0x18#define ADC1_AWS3_vector 0x18#define ADC1_AWS4_vector 0x18#define ADC1_AWS5_vector 0x18#define ADC1_AWS6_vector 0x18#define ADC1_EOC_vector 0x18#define ADC1_AWS8_vector 0x18#define ADC1_AWS9_vector 0x18#define ADC1_AWDG_vector 0x18#define ADC1_AWS7_vector 0x18#define TIM4_OVR_UIF_vector 0x19#define FLASH_EOP_vector 0x1A#define FLASH_WR_PG_DIS_vector 0x1A对照中断向量表,如果⽤到中断,必须⾃⼰写中断,⽐如TIM3定时器中断#pragma vector=TIM3_OVR_UIF_vector__interrupt void TIM3_UPD_OVF_IRQHandler (void){TIM3_SR = 0X00;//清除中断标志}⽤关键字#pragma vector=指出本中断处理函数指向的中断号,⽤关键字__interrupt作为函数的前缀,表⽰这是中断处理函数。

STM8低功耗设定及其例程

STM8低功耗设定及其例程

STM8低功耗设定及其例程STM8有三种低功耗模式,即等待、活跃停机和停机。

具体它们三者有什么区别自己看官方手册去吧,这里只讲停机模式的应用,其他的一笔带过!一、进入的方式:等待模式进入用的指令是WFI,而活跃停机和停机用的都是halt(),所不同的是,在执行halt指令之前,如果开启了AWU,则是活跃停机,反之则是停机。

还有一点要说明的是,在停机模式下独立看门狗是不能养的,而只能养窗口看门狗。

二、具体进入的步骤:1、首先,你声明一个标志位,名字自己取。

这个标志位是用来判断系统是该处于运行模式还是处于停机模式的。

我这里用fPowerOn_flag,如下:bool fPowerOn_flag = FALSE;有了这个标志位以后就写下面的部分了:int main(void){//设置内部16M晶振为系统时钟Clk_Init(); //系统时钟初始化函数MWWDG_Init();//窗口看门狗初始化函数while (1){Free_WWDG();//喂狗函数if(fPowerOn_flag == FALSE){Halt_OffDevice();//停机前关闭不需要的外设halt();//进入停机模式System_Init();//系统初始化函数}if(fPowerOn_flag){//运行代码在这里添加}}}以上就是一个停机模式的模板了,大家参照着用就可以了。

系统上电默认是进入停机模式,然后通过按键唤醒进入运行模式。

下面为大家讲一下主函数中每个函数的写法和功能吧!2、各函数说明:a、时钟初始化函数:void Clk_Init(void){CLK_DeInit();//复位时钟寄存器CLK_HSICmd(ENABLE);//使能内部高速时钟CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV4);//配置内部高速时钟(时钟分频器:4分频),系统时钟4MHzCLK_ClockSecuritySystemEnable();//开启时钟安全系统}这个函数我想不用多讲了,大家都懂的。

STM8S定时器2产生PWM波形

STM8S定时器2产生PWM波形

/*初始化自动装载寄存器,决定PWM方波的频率,Fpwm=2000000/1250=1.6Khz 定时器时钟默认为内部时钟8分频,即HSI / 8 = 2MHz*/ 5、TIM2_ARRH = 0x04; // 自动重载寄存器ARR=0x04e2=1250 6、TIM2_ARRL = 0xE2; // 每1250次产生一次中断 /*决定PWM方波的占空比 */ 7、 TIM2_CCR1H = 0x02; 8、 TIM2_CCR1L = 0x71; ARR与CCRi决定PWM的频率和占空比,当计数器工作使能以后,CNT会按照当 前频率计数,当CNT<CCRi的值时,PWM参考信号为无效电平,否则为有效电平, 有效电平为高或者为低,可通过软件在TIM2_CCERi寄存器中的CCiP位设置。当 CNT=ARR时,产生溢出,进入中断, 一个周期结束。 /* 初始化时钟分频器为1,即计数器的时钟频率为Fmaster=2Mhz */ 9、TIM2_PSCR = 0x00;//分频系数为0,不进行分频;设置分频系数 10、TIM2_IER |= 0x02;//禁止更新中断,通道1 中断允许 产生中断后需进入中断清楚标志位,否则程序会死在中断里 11、TIM2_CR1 |= 0x01;//使能计数度调制(PWM)模式可以产生一个由TIM2_ARR寄存器确定频率、由 TIM2_CCRi寄存器确定占空比的信号。 1、CLK_PCKENR1 |= 0x20; //TIM2外设时钟使能 STM8S外设时钟默认全部使能的,如果没有禁止外设时钟,此段程序可省略 2、TIM2_CR1 = 0x00;//禁止计数器 计数器一般先配置参数,最后使能 3、TIM2_CCMR1 |= 0x70; // Output mode PWM2. // 通道1被设置成比较输出方式 // OC2M = 111,为PWM模式2, // 向上计数时,若计数器小于比较值,为无效电平 // 即当计数器在0到比较值时,输出为1,否则为0 4、TIM2_CCER1 |= 0x03;/* CC polarity low,enable PWM output CC1P = 1,低电平为有效电平 CC1E = 1,开启输出引脚

STM8教程-第十四章 STM8S207 PWM 模块及其应用实例

STM8教程-第十四章 STM8S207 PWM 模块及其应用实例

第十四章STM8S207 PWM 模块及其应用实例上一节我们学习了定时器中的基本定时器编程,这一节学习定时器里面一个PWM模块。

当终于到了PWM 模块编程时,有些许怀念,怀念过去的一年之中的日以继夜相对的PWM。

忘了介绍我们的团队---风驰,也就是第六届飞思卡尔比赛中的一个队伍。

1、PWM 介绍脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。

简单一点,就是对脉冲宽度的控制。

PWM 在实际应用很广,例如上面提到的飞思卡尔智能车就用到PWM 控制舵机以及电机。

关于舵机是如何用PWM 控制的,这里不详细说明,有兴趣的建议查询相关知识。

这些在模型制作中应用十分广泛。

关于PWM 如果控制电机的这里略为说明,因为和本节有些许关联普通直接电机在通电时以全电压工作,在没有PWM 控制电机之前是运用继电器通过不停开断实现对电机的速度控制。

引入PWM 就可以更为灵活控制电机。

PWM 是脉冲宽度可调的方波,在10K 左右的频率下,通过不同的占空比就可以得到近似稳定的电压。

例如输入5V,占空比为50%时,电压近似 2.5V。

我们这节实验也是应用PWM 这个特性。

利用PWM 中的占空比调节LED 的亮度。

关于PWM 的说明这里也简要说明,PWM 第一个参数是PWM 的周期,也就是一个PWM 的时间。

这个可以通过对应的寄存器进行设置,而我们的STM8S207 通过PSCR 设置定时器的时钟源CK_CNT,然后再通过ARR 寄存器设置周期。

例如我们这节的实验使用了16M 内部时钟源,LED4 是接着PD3 的,也就是TIM2_CH2,PSCR只能是2 的次幂,我们选择了4 分频。

CK_CNT = 4M,然后ARR 设置为200,分频200 后直接提供PWM 的时钟,所以f_pwm = 4M/200 = 20KHz。

STM8单片机TIME1-PWM应用

STM8单片机TIME1-PWM应用
关于极性,结合本例 led 的连接方式,选择 OC1 低电平有效
通过以上 配置,比 较模块可 以工作了
计数器高 8 位(TIM1_CNTRH) 计数器低 8 位(TIM1_CNTRL)
这两个寄存器存放着 Tim 1 的当前计数值
预分频器的高 8 位(TIM1_PSCRH) TIM1 的分频系数从 1~65535 之间任意 预分频器的低 8 位(TIM1_PSCRL) 自动重装载寄存器高 8 位(TIM1_ARRH) TIM1 的计数最大值 自动重装载寄存器低 8 位(TIM1_ARRL) 捕获/比较寄存器 1 高 8 位(TIM 1_CCR1H) 通过设置目标通道的比较值来设置 PWM 的占空比 捕获/比较寄存器 1 低 8 位(TIM 1_CCR1L) 普通定时器到此就 ok 了,但是 TIM1 却不行,还缺一步(因其功能更强大,多 了刹车功能) 刹车寄存器(TIM 1_BKR)TIM 1->BKR|=0x80 原理: 比较 TIM 1_CNT、TIM 1_ARR(3 者中最大值) 、TIM1_CCR1 ,根据前面选择的 PWM 模式 1 中的规定知:向上计数时, TIM1_CNT < TIM1_CCR1 时通道 1 为 有效电平(本例有效电平为低) ,所以 TIM 1_CCR1 的值越大,低电平的时间越 长,led 亮的时间越长 所以程序中要进行如下操作: 1. 其余寄存器初始化 2. 不断改变 TIM 1->CCR1H、TIM1->CCR1L 的值(即 PWM 占空比)
TIME1-PWM 例程简单讲解归纳
对于 PWM 信号,主要涉及到两个概念:一个就是 PWM 信号的周期或频率, 另一个就是 PWM 器模块。 涉及寄存器: 控制寄存器(TIM 1_CR1=0X01;// 启动定时器) 捕获/比较模式寄存器(TIM 1_CCMR1 通道设置为输出,选择 PWM 模式 1) 捕获/比较使能寄存器(TIM 1_CCER1 使能比较输出和设置 PWM 的极性)

STM8S定时器的使用

STM8S定时器的使用

STM8S定时器的使用/liuyu60305002/article/details/6951916 2011看了网上的资源,都不怎么好用,于是决定总结总结,记录下定时器的简单实用方法。

环境: STM8SF103 ,仿真器为:STLINKTIM4 属于8位定时器,最大128分频。

这个定时器的时钟源是系统时钟源(fMaster),然后直接通过预分频器分频后供CK_CNT使用。

如:系统频率为4MHz,经过128分频后,提供给定时器使用的频率就为 31250Hz因为项目需要,我这里使用的内部RC 16MHz振荡器,并进行LSI 4分频,所以主频为4MHz。

[cpp] view plain copy1.//main.c2.void Init_Tim4(void)3.{4./*很多人都是在这里装填0xFF,其实是为了让PSC尽快生效,对于PSC的设置,需要在下一个更新事件时才会生效*/5.TIM4_CNTR=0; //计数器值6.TIM4_ARR=0xFA; //自动重装寄存器 250,产生125次定时1S7.TIM4_PSCR=0x07; //预分频系数为1288.TIM4_EGR=0x01; //手动产生一个更新事件,用于PSC生效注意,是手动更新9.10.TIM4_IER=0x01; //更新事件中断使能11.TIM4_CR1=0x01; //使能计时器,TIM4_CR0停止计时器12.}13.14.void main(void)15.{16._asm("rim"); //这是必须的,因为系统重启后,软件中断级别为3级,处于最高级,除了TRAP,TLI,RESET三个中断外不响应其他中断。

17.//rim将软件级别更改为0级别,这样其他中断就能得到相应。

18.Init_Tim4();19.while(1);20.}21.22.//中断向量表必须将TIM4的中断处理函数填写进去23.{0x82, TIM4_UPD_OVF_IRQHandler}, /* irq23 */24.25.//处理函数如下:26./*定时器4用作看门狗喂狗定时,因为看门狗最大延时510ms,27.定时器频率为4MHz/128=31250 = 250 * 125,125 / 5 = 25 (200ms)*/28.@far @interrupt void TIM4_UPD_OVF_IRQHandler(void)29.{30.t4++;31.TIM4_SR=0; //清除中断标志32.//t4==125 //定时1S33.if(t4==25) //25 * 250 定时200ms34.{35.FREE_IWDG; //喂狗,如果单纯定时用,可以拿掉36.//可以尝试点亮LED灯37.t4=0;38.}39.return;40.}定时器延时计算过程,如主频4MHz,预分频为128,定时器频率等于 4000000 / 128 = 31250 (Hz),周期为32us。

STM8例程—音乐播放(使用定时器PWM)

STM8例程—音乐播放(使用定时器PWM)
* 名称:音乐播放 *
作者:宇辰_hong *
Music_Num=Music_Num+3;
if(Music_Num&gt;74)
M
usic_Num=0;
}
TIM2_ARRH=FREQH[Music_Freq]/256;
TIM2_ARRL=FREQH[Music_Freq]%256;
PWM=FREQH[Music_Freq]/8;
TIM2_CCR1H=PWM/256; //PWM占空比为%20
TIM2_CCR1L=PWM%256;
5,1,1, 5,1,1, 6,1,2, 5,1,2, 2,2,2, 1,2,4,
5,1,1, 5,1,1, 5,2,2, 3,2,2, 1,2,2, 7,1,2, 6,1,2,
4,2,1, 4,2,1, 3,2,2, 1,2,2, 2,2,2, 1,2,4};
//音乐数据,三个数据为一组,其中第一个数据表示音调,第二个数据表示音调高低,其中1为低8度,2为正常,3为高8度
} ;
//音阶频率表,根据每个音调的频率(网上可查),以及定时器的频率计算出来的
void Time2_Init(void);
void Time3_Init(void);
void main( void )
{
Time2_Init();
Time3_Init();
asm(&quot;RIM&quot;);
/************************广东工业大学电子科技协会******************** *
while(1)
{
}
}

STM8学习笔记——PWM模块

STM8学习笔记——PWM模块

STM8学习笔记——PWM模块首先将管脚配置为推挽输出。

下面以向上计数模式为例来讲述PWM 产生的原理:TIMx 开始向上计数,TIMx_CNT 为计数值,计数一次加1,TIMx_ARR 确定了计数的上限,达到上限后计数器从0 开始重新计数,所以一次PWM 频率就由TIMx_ARR 来确定了,即计数器时钟*(TIMx_ARR-1),频率确定了,接下来就是占空比。

占空比是由TIMx_CCRx 来确定的,PWM模式1 下当TIMx_CNT=TIMx_CCRx 时,输出OCiREF 无效电平,至于有效电平是0 还是1,要设置TIMx_CCERx,这样产生了一个PWM 波形,可以说配置非常灵活,当TIMx_CCRx 为0 时,占空比就为0,当TIMx_CCRx 大于TIMx_ARR 时,就一直输出高电平(占空比100%)。

下图是个例子:以下是我写的一个参考程序,测试通过void TIM1_Init(void){//定时器1 初始化CLK_PCKENR1|=0x80;//开启定时器1 外设时钟TIM1_EGR=0x01;//重新初始化TIM1 TIM1_EGR|=0x20;//重新初始化TIM1 TIM1_ARRH=0x00;//设定重装载值TIM1_ARRL=254; TIM1_PSCRH=0;//预分频TIM1_PSCRL=9; TIM1_CR1=0;//边沿对齐,向上计数} void TIM1_PWM_Init(){ //TIM1_CCER1=0x03;//低电平有效//TIM1_CCMR1=0x70;//PWM 模式2TIM1_CCER1=0x01;//高电平有效TIM1_CCMR1=0x60;//PWM 模式1TIM1_CCR1H=0;//占空比TIM1_CCR1L=50; TIM1_CR1|=0x01;//向上计数,无缓存,使能TIM1_BKR=0x80;//开启刹车}tips:感谢大家的阅读,本文由我司收集整编。

STM8单片机ADC、Timer、USART寄存器直接操作实用例程

STM8单片机ADC、Timer、USART寄存器直接操作实用例程

STM8 单片机ADC、Timer、USART实用例程这是一个我花了较长时间摸索出来的STM8L-051的例程,它控制LED灯,Timer2定时100us进入中断,软件启动ADC,采样10 次后取平均,将结果通过UASART发送至PC 机,在超级终端上显示的实用程序,因其内存极小,不能用printf等函数,因此对于想用这款资源极少的MCU的开发者来说,读这篇文章会大大节约你的研发时间。

有不会的问题请发邮件***************。

#include <stdio.h>#include "stm8l15x.h"#include "iostm8l051f3.h"#define LED_GPIO_PORT GPIOA#define LED_GPIO_PINS GPIO_Pin_2 | GPIO_Pin_3/* Private function prototypes -----------------------------------------------*/#define ADC1_DR_ADDRESS ((uint16_t)0x5344)#define BUFFER_SIZE ((uint8_t) 0x02)#define BUFFER_ADDRESS ((uint16_t)(&Buffer))#define ASCII_NUM_0 ((uint8_t) 48)#define ADC_RATIO ((uint16_t) 806) /*ADC_RATIO = ( 3.3 * 1000 * 1000)/4095*/#define SampleADC ((uint8_t) 0x0A)/* Private variables ---------------------------------------------------------*/uint8_t Buffer[4] = {0, 0, 0, 0};uint16_t ADCdata = 0;uint16_t ADCvalue = 0;unsigned char LED =1;unsigned char c = 8;uint16_t acode = 1234; //43 "+" 0x2B;void Delay(__IO uint16_t nCount){/* Decrement nCount value */while (nCount != 0){nCount--;}}//int putchar(int c)//{// while ((USART1_SR&0x80)==0x00);// UART2_sendchar((u8)c);// return (c);//}static void CLK_Config(void){/* Select HSI as system clock source */CLK_SYSCLKSourceSwitchCmd(ENABLE);CLK_SYSCLKSourceConfig(CLK_SYSCLKSource_HSI); /*High speed external clock prescaler: 1*/CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_1);while (CLK_GetSYSCLKSource() != CLK_SYSCLKSource_HSI){}/* Enable ADC1 clock */CLK_PeripheralClockConfig(CLK_Peripheral_ADC1, ENABLE);/* Enable DMA1 clock */// CLK_PeripheralClockConfig(CLK_Peripheral_DMA1, ENABLE);/* Enable TIM2 clock */CLK_PeripheralClockConfig(CLK_Peripheral_TIM2, ENABLE);CLK_PeripheralClockConfig(CLK_Peripheral_USART1, ENABLE); }static void GPIO_Config(void){PC_DDR = 0X20;PC_CR1 = 0X20;PA_DDR = 0X0C;PA_CR1 = 0X0C;}static void USART1_Config(void){// ADCvalue = USART1_DR;USART1_BRR2 = 0x03;USART1_BRR1 = 0x68; //16M/9600=683USART1_CR2 = 0x0C; //Transmitter & receiver enable}static void ADC_Config(void){ADC1_CR2 = 0x22; //risign edge, softwae start, sampling time 16 ADC clockADC1_SQR3 = 0x80; //ADC = 15channelADC1_TRIGR1 = 0x10; //use internal ref,sampling time 16 ADC clock for RefRI_ASCR1 = 0x00;}void TIM2_Config(void){TIM2_PSCR = 0x07; // 应是16,但只能置三位,所以是111 fCK_PSC / 2(PSC[2:0]).// TIM2_PSCRL = 0x3F; // PSCR=0x1F3F,f=8M/(0x1F3F+1)=1000Hz,每个计数周期1ms TIM2_ARRH = 0x00; // 自动重载寄存器ARR=0x01F4=500TIM2_ARRL = 0x18; // 24X4us=96us 每记数500次产生一次中断,即500msTIM2_IER = 0x01; // 允许更新中断TIM2_CR1 = 0x05; // 计数器使能,开始计数,只允许更新中断请求}void Delay (uint16_t nCount);/* Private functions ---------------------------------------------------------*///#pragma vector = ADC1_EOC_vector//__interrupt void ADC1_EOC(void)//{// ADCdata = ADC_GetConversionValue(ADC1);// }#pragma vector =TIM2_OVR_UIF_vector__interrupt void TIM2_OVR_UIF(void){asm("sim");static uint8_t measurements = SampleADC;static uint32_t accumulator = 0;uint32_t average = 0;uint16_t factor10 = 1000;int8_t i ;ADCdata = 0;TIM2_SR1 = 0x00; //Clear UIFADC1_SR = 0x00; //Clear EOCADC1_CR1 = 0x03; // EOC interrupt unable, software set start, ADC enable// while (!(ADC1_SR & 0x01));/*最后一位不是1,结果就是全零,结果为False,!则是True,循环下去;若是1,则跳出。

STM8S103 PWM实例

STM8S103 PWM实例
= 0x10;
PB_CR2 = 0x00;
PC_DDR = 0x00;
PC_CR1 = 0x10;
PC_CR2 = 0x00;
PD_DDR = 0x00;
PD_CR1 = 0x60;
PD_CR2 = 0x00;
CLK_SWCR_SWEN = 1; // 时钟切换寄存器,0禁止1使能
* 函数名称:
* 功 能:
* 说 明:
* 入口参数:
* 返回值:
* 作 者: X.Y.Xiao 时间: ×年×月×日
* 修 改: 时间:
******************************************************************************/
return Dat;
}
//-------------------------------------------------------
void eeprom_write_word(unsigned int address,unsigned int Data)
{
FLASH_DUKR = 0xae; // 第2硬件密匙。
TIM1_CNTRH = 0; // 计数器清0
TIM1_CNTRL = 0;
TIM1_PSCRH = 0; // 预分频器清0
TIM1_PSCRL = 0;
TIM1_ARRH = (unsigned char)(FrePeriod/256); //自动重装值高位
TIM1_ARRL = (unsigned char)FrePeriod; //自动重装值低位
#define EEP_ADDRESS_WIDTH2 0x4022

STM8教程实验8-定时器TIM1

STM8教程实验8-定时器TIM1

STM8教程实验8-定时器TIM1例程⼋ TIM1这⼀节,我们将向⼤家介绍如何使⽤STM8的定时器中的基本定时功能,STM8的定时器功能⼗分强⼤,有TIM1⾼级定时器,也有TIM2、TIM3等通⽤定时器,还有TIM4基本定时器。

在STM8S参考⼿册⾥⾯,定时器的介绍占了1/3的篇幅,⾜见其重要性。

这⼀节,我们分别介绍TIM1的基本定时功能16位⾼级控制定时器(TIM1)简介:TIM1由⼀个16位的⾃动装载计数器组成,它由⼀个可编程的预分频器驱动。

TIM1有4个通道,分别是1到4。

分别对应于四个不同的捕获/⽐较通道。

⾼级控制定时器适⽤于许多不同的⽤途:基本的定时测量输⼊信号的脉冲宽度(输⼊捕获)产⽣输出波形(输出⽐较,PWM和单脉冲模式)对应与不同事件(捕获,⽐较,溢出,刹车,触发)的中断与TIM5/TIM6或者外部信号(外部时钟,复位信号,触发和使能信号)同步⾼级控制定时器⼴泛的适⽤于各种控制应⽤中,包括那些需要中间对齐模式PWM的应⽤,该模式⽀持互补输出和死区时间控制。

⾼级控制定时器的时钟源可以是内部时钟,也可以是外部的信号,可以通过配置寄存器来进⾏选择。

TIM1的时基单元包括,如下图所⽰:● 16位向上/向下计数器● 16位⾃动重载寄存器●重复计数器●预分频器16位计数器,预分频器,⾃动重载寄存器和重复计数器寄存器都可以通过软件进⾏读写操作。

⾃动重载寄存器由预装载寄存器和影⼦寄存器组成。

可在在两种模式下写⾃动重载寄存器:●⾃动预装载已使能(TIM1_CR1寄存器的ARPE位置位)。

在此模式下,写⼊⾃动重载寄存器的数据将被保存在预装载寄存器中,并在下⼀个更新事件(UEV)时传送到影⼦寄存器。

●⾃动预装载已禁⽌(TIM1_CR1寄存器的ARPE位清除)。

在此模式下,写⼊⾃动重载寄存器的数据将⽴即写⼊影⼦寄存器。

更新事件的产⽣条件:●计数器向上或向下溢出。

●软件置位了TIM1_EGR寄存器的UG位。

STM8的C语言编程(5)--8位定时器应用之一

STM8的C语言编程(5)--8位定时器应用之一

STM8的C语言编程(5)--8位定时器应用之一在STM8单片机中,有多种定时器资源,既有8位的定时器,也有普通的16位定时器,还有高级的定时器。

今天的实验是用最简单的8位定时器TIM4来进行延时,然后驱动LED闪烁。

为了简单起见,这里是通过程序查询定时器是否产生更新事件,来判断定时器的延时是否结束。

同样还是利用ST的开发工具,生成一个C程序的框架,然后修改其中的main. c,修改后的代码如下。

编译通过后,下载到开发板,运行程序,可以看到LED在闪烁,或者用示波器可以在LED引脚上看到方波。

在这里要特别提醒的是,从ST给的手册上看,这个定时器中的计数器是一个加1计数器,但本人在实验过程中感觉不太对,经过反复的实验,我认为应该是一个减1计数器(也许是我拿的手册不对,或许是理解上有误)。

例如,当给定时器中的自动装载寄存器装入255时,产生的方波频率最小,就象下面代码中计算的那样,产生的方波频率为30HZ左右。

若初始化时给自动装载寄存器装入1,则产生的方波频率最大,大约为3.9K左右。

也就是说实际的分频数为ARR寄存器的值+1。

// 程序描述:通过初始化定时器4,进行延时,驱动LED闪烁// LED接在MCU的GPIO的PD3上#include "STM8S207C_S.h"main(){// 首先初始化GPIOPD_DDR = 0x08;PD_CR1 = 0x08; // 将PD3设置成推挽输出PD_CR2 = 0x00;// 然后初始化定时器4TIM4_IER = 0x00; // 禁止中断TIM4_EGR = 0x01; // 允许产生更新事件TIM4_PSCR = 0x07; // 计数器时钟=主时钟/128=2MHZ/128// 相当于计数器周期为64uSTIM4_ARR = 255; // 设定重装载时的寄存器值,255是最大值TIM4_CNTR = 255; // 设定计数器的初值// 定时周期=(ARR+1)*64=16320uSTIM4_CR1 = 0x01; // b0 = 1,允许计数器工作// b1 = 0,允许更新// 设置控制器,启动定时器while(1) // 进入无限循环{while((TIM4_SR1 & 0x81) == 0x00); // 等待更新标志TIM4_SR1 = 0x00; // 清除更新标志PD_ODR = PD_ODR ^ 0x08; // LED驱动信号取反// LED闪烁频率=2MHZ/128/255/2=30.63 }}。

STM8的C语言编程(14)-- PWM

STM8的C语言编程(14)-- PWM

STM8的C语言编程(14)--PWM在单片机应用系统中,也常常会用到PWM信号输出,例如电机转速的控制。

现在很多高档的单片机也都集成了PWM功能模块,方便用户的应用。

对于PWM信号,主要涉及到两个概念,一个就是PWM信号的周期或频率,另一个就是PWM信号的占空比。

例如一个频率为1KHZ,占空比为30%,有效信号为1的PWM信号,在用示波器测量时,就是高电平的时间为300uS,低电平的时间为700uS的周期波形。

在单片机中实现PWM信号的功能模块,实际上就是带比较器的计数器模块。

首先该计数器循环计数,例如从0到N,那么这个N就决定了PWM的周期,PW M周期=(N+1)*计数器时钟的周期。

在计数器模块中一定还有一个比较器,比较器有2个输入,一个就是计数器的当前值,另一个是可以设置的数,这个数来自一个比较寄存器。

当计数器的值小于比较寄存器的值时,输出为1(可以设置为0),当计数器的值大于或等于比较寄存器的值时,输出为0(也可设置为1,与前面对应)。

了解了这个基本原理后,我们就可以使用STM8单片机中的PWM模块了。

下面的实验程序首先将定时器2的通道2设置成PWM输出方式,然后通过设置自动装载寄存器TIM2_CCR2,决定PWM信号的周期。

在程序的主循环中,循环修改占空比,先是从0逐渐递增到128,然后再从128递减到0。

当把下面的程序在ST的三合一板上运行时,可以看到发光二极管LD1逐渐变亮,然后又逐渐变暗,就这样循环往复。

如果用示波器看,可以看到驱动LD1的信号波形的占空比从0变到50%,然后又从50%变到0。

同样还是利用ST的开发工具,生成一个C语言程序的框架,然后修改其中的m ain.c,修改后的代码如下。

// 程序描述:用PWM输出驱动LED#include "STM8S207C_S.h"void CLK_Init(void);void TIM_Init(void);// 函数功能:延时函数// 输入参数:ms -- 要延时的毫秒数,这里假设CPU的主频为2MHZ// 输出参数:无// 返回值:无// 备注:无void DelayMS(unsigned int ms){unsigned char i;while(ms != 0){for(i=0;i<250;i++){}for(i=0;i<75;i++){}ms--;}}// 函数功能:初始化时钟// 输入参数:无// 输出参数:无// 返回值:无// 备注:无void CLK_Init(){CLK_CKDIVR = 0x11; // 10: fHSI = fHSI RC output/ 4// = 16MHZ / 4 =4MHZ// 001: fCPU=fMASTER/2. = 2MHZ}// 函数功能:初始化定时器2的通道2,用于控制LED的亮度// 输入参数:无// 输出参数:无// 返回值:无// 备注:无void TIM_Init(){TIM2_CCMR2 = TIM2_CCMR2 | 0x70;// Output mode PWM2.// 通道2被设置成比较输出方式// OC2M = 111,为PWM模式2,// 向上计数时,若计数器小于比较值,为无效电平// 即当计数器在0到比较值时,输出为1,否则为0TIM2_CCER1 = TIM2_CCER1 | 0x30;// CC polarity low,enable PWM ou tput */// CC2P = 1,低电平为有效电平// CC2E = 1,开启输出引脚//初始化自动装载寄存器,决定PWM方波的频率,Fpwm=4000000/256=1562 5HZTIM2_ARRH = 0;TIM2_ARRL = 0xFF;//初始化比较寄存器,决定PWM方波的占空比TIM2_CCR2H = 0;TIM2_CCR2L = 0;// 初始化时钟分频器为1,即计数器的时钟频率为Fmaster=4MHZTIM2_PSCR = 0;// 启动计数TIM2_CR1 = TIM2_CR1 | 0x01;}main(){unsigned char i;CLK_Init(); // 初始化时钟TIM_Init(); // 初始化定时器while(1) // 进入无限循环{// 下面的循环将占空比逐渐从0递增到50%for(i=0;i<128;i++){TIM2_CCR2H = 0;TIM2_CCR2L = i;DelayMS(5);}// 下面的循环将占空比逐渐从50%递减到0for(i=128;i>0;i--){TIM2_CCR2H = 0;TIM2_CCR2L = i;DelayMS(5);}}}。

STM8 Nucleo-64板使用TIM外设生成PWM信号应用说明书

STM8 Nucleo-64板使用TIM外设生成PWM信号应用说明书

AN5180使用STM8 Nucleo-64板生成PWM信号引言NUCLEO-8S208RB(基于STM8S208RBT6器件构建)和NUCLEO-8L152R8(基于STM8L152R8T6器件构建)板能够评估所有STM8S系列和STM8L系列微控制器的主要功能。

本应用笔记提供了如何使用TIM定时器外设生成三个PWM信号的简要说明。

表 1. 适用产品参考文档•STM8 Nucleo-64板数据摘要(DB3591)•STM8L152R8T6 Nucleo-64板用户手册(UM2351)•STM8S208RBT6 Nucleo-64板用户手册(UM2364)1应用描述本章说明了硬件需求、应用原理图以及应用在NUCLEO-8S208RB或NUCLEO-8L152R8板上使用TIM外设生成三个PWM信号的应用原理。

1.1硬件要求在NUCLEO-8S208RB或NUCLEO-8L152R8开发板,无需额外硬件。

示波器一台1.2应用原理图两个板的应用原理图如下图所示。

图 1. STM8S系列应用原理图图 2. STM8L系列应用原理图1.3应用原理本应用使用TIM的PWM(脉冲宽度调制)模式,来生成三个PWM 信号。

•对于STM8S 系列器件,使用TIM2•对于STM8L系列器件,使用TIM1生成的过程如下图所示。

图 3. PWM生成原理根据定时器计数器时钟,TIM从0开始计数,增加到自动加载寄存器的值(TIM_ARR)。

•当计数器值等于比较/捕获寄存器(TIM_CCRx)值时,通道x信号置为0。

•当计数器值达到TIM_ARR值时,计数器复位,通道x信号置为1。

通过配置TIMx_CCRx和TIMx_ARR寄存器,用户可方便地修改所生成PWM信号的占空比和频率(请参见第 2 节软件说明)。

默认情况下,应用提供三种PWM信号,如下表所述。

提示能够配置AFR选项字节,在PD2上也得到通道3。

表 2. 默认的PWM信号2软件说明本例使用STM8S系列和STM8L系列标准固件库来驱动通用外设的功能。

STM8TIM定时器要点

STM8TIM定时器要点

STM8TIM定时器要点STM8 TIM 定时器使用要点:1、分频:TIM1 可以在(1~65536)之间任意分频:Fck_cnt=Fck_psc/(PSCR[15:0]+1)先写高字节,后写低字节,更新事件后生效。

TIM2/TIM3/TIM5 可以在(1~32768)之间以2的幂分频:Fck_cnt=Fck_psc/(2^(PSCR[3:0]))更新事件后生效。

2、预装载:ARR/OCiR预装载允许时(ARPE=1 OCiPE=1),写入的寄存器值不会直接进入影子寄存器,需要发生一次更新事件后,才生效。

ARR/OCiR预装载禁止时(ARPE=0 OCiPE=0),写入的寄存器值直接进入影子寄存器,立即生效,因此可能造成第一次的波形不正常。

3、更新:置位TIMx_EGR的UG位可以软件生成一个更新事件。

向上计数方式时,CNT从ARR跳变到0时产生更新事件。

向下计数方式时,CNT从0跳变到ARR时产生更新事件。

向上/向下计数方式时(中央对齐模式),OCRi寄存器的值是比较值(OCiREF的有效时间)的一半,ARR寄存器的值是实际周期值(不用-1)的一半,CNT从ARR-1增加到ARR时产生上溢事件,CNT从1减少到0时产生下溢事件。

安全使用中央对齐模式的计数器的方法是在启动计数器之前先用软件(置位TIM1_EGR寄存器的UG位)产生一个更新事件,并且不在计数器计数时修改计数器的值。

4、PWM模式:PWM边沿对齐PWM1模式,向上计数时,CCRx正确取值范围为(0~ARR):CCRx=0 时,产生全无效电平(产生占空比为0%的PWM波形)。

CCRx<=ARR 时,产生CCRx个有效电平(产生占空比为CCRx/(ARR+1)*100% 的PWM波形)。

CCRx>ARR 时,产生全有效电平。

PWM边沿对齐PWM1模式,向下计数时,CCRx正确取值范围为(0~ARR):CCRx=0 时,不能产生占空比0% 的PWM波形(产生占空比为1/(ARR+1)*100%的PWM波形)。

STM8 PWM模式

STM8 PWM模式

STM8 PWM模式STM8的脉冲宽度调制(PWM)模式可以产生一个由TIM1_ARR寄存器确定频率、由TIM1_CCRi寄存器确定占空比的信号。

在TIM1_CCMRi寄存器中的OCiM位写入'110'(PWM模式1)或'111'(PWM模式2),能够独立地设置每个OCi输出通道产生一路PWM。

必须设置TIM1_CCMRi寄存器的OCiPE位使能相应的预装载寄存器,也可以设置TIM1_CR1寄存器的ARPE位使能自动重装载的预装载寄存器(在向上计数模式或中央对称模式中)。

由于仅当发生一个更新事件的时候,预装载寄存器才能被传送到影子寄存器,因此在计数器开始计数之前,必须通过设置TIM1_EGR寄存器的UG位来初始化所有的寄存器。

OCi的极性可以通过软件在TIM1_CCERi寄存器中的CCiP位设置,它可以设置为高电平有效或低电平有效。

OCi的输出使能通过(TIM1_CCERi和TIM1_BKR寄存器中)CCiE、MOE、OISi和OSSR位和OSSI 位的组合来控制。

详见TIM1_CCERi寄存器的描述。

在PWM模式(模式1或模式2)下,TIM1_CNT和TIM1_CCRi始终在进行比较,(依据计数器的计数方向)以确定是否符合TIM1_CCRi≤TIM1_CNT或者TIM1_CNT≤TIM1_CCRi。

根据TIM1_CR1寄存器中CMS位域的状态,定时器能够产生边沿对齐的PWM信号或中央对齐的PWM 信号。

PWM边沿对齐模式向上计数配置当TIM1_CR1寄存器中的DIR位为低的时候执行向上计数。

下面是一个PWM模式1的例子。

当TIM1_CNT<TIM1_CCRi时,PWM参考信号OCiREF为高,否则为低。

如果TIM1_CCRi中的比较值大于自动重装载值(TIM1_ARR),则OCiREF保持为'1'。

如果比较值为0,则OCiREF保持为'0'。

stm8s开发(五) TIMER的使用:定时!

stm8s开发(五) TIMER的使用:定时!

stm8s 开发(五)TIMER 的使用:定时!
STM8S提供三种类型的TIM定时器:高级控制型(TIM1)、通用型(TIM2/TIM3/TIM5)和基本型定时器(TIM4/TIM6)。

它们虽有不同功能但都基于共同的架构。

此共同的架构使得采用各个定时器来设计应用变得非常容易与方便(相同的寄存器映射,相同的基本功能)。

使用定时可以确定一个时间片,方便控制发送速率,采样速率,等等一些对时间要求比较高的任务,而这些操作可以放入定时器中断里面执行。

这次的例子,定时1s,让LED灯翻转一次,达到2s闪烁一次的效果。

由于定时操作简单,我们使用基本定时器:TIMER4
voidInit_Timer4(void)
{
//128分频256计数,在16MHz下是2.048ms一次中断!
//128分频256计数,在128KHz下是256ms一次中断!
TIM4_CR1=0x00;//关闭计数器
//TIM4_IER=0x00;
TIM4_IER=0x01;//更新中断使能
TIM4_EGR=0x01;
TIM4_CNTR=255;//计数器值
TIM4_ARR=255;//自动重装的值
TIM4_PSCR=0x07;//分频值
TIM4_CR1=0x01;//使能计数器
}
值得注意的是,如果我们使用16M为主时钟的话,通过最大分频和最大。

stm8C语言例程

stm8C语言例程

(1);名称:流水灯;描述 : ;先从上至下点亮所有的LED,再逐个点亮单个LED;***********************************************************/#include "stm8s105s4.h"#define uchar unsigned char#define uint unsigned intuchar table[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //存放点亮单个LED的代码void DelayMS(uint s) //延时子函数,约延时1ms{uint i;for(s;s>0;s--)for(i=0;i<500;i++);}void init(void) //stm8初始化函数{PB_DDR = 0xff;PB_CR1 = 0xff; // 将PB设置成推挽输出PB_CR2 = 0x00;CLK_SWR = 0xE1; //选部高速时钟作为主时钟CLK_CKDIVR = 0x08; //将CPU主频设置为2M(STM8默认的就是部高速时钟的八分频,即2MH,这里只是告诉大家设置方法)}void main(){uchar i;init();while (1) //无限循环{PB_ODR = 0xff; //先将所有的LED关闭for(i=0;i<9;i++) //一开始是所有的LED熄灭,再逐点亮所有LED,共九种状态{DelayMS(500); //延时500毫秒PB_ODR<<=1; //将PB_ODR向左移动一位,逐渐点亮所有LED }for(i=0;i<8;i++){PB_ODR=table[i]; //将table中的数依次赋给PB_ODR ,从上至下依次点亮LEDDelayMS(500);}}}中断向量:/* BASIC INTERRUPT VECTOR TABLE FOR STM8 devices* Copyright (c) 2007 STMicroelectronics*/typedef void far (*interrupt_handler_t)(void);struct interrupt_vector {unsigned char interrupt_instruction;interrupt_handler_t interrupt_handler;};far interrupt void NonHandledInterrupt (void){/* in order to detect unexpected events during development,it is remended to set a breakpoint on the following instruction */return;}extern void _stext(); /* startup routine */struct interrupt_vector const _vectab[] = {{0x82, (interrupt_handler_t)_stext}, /* reset */{0x82, NonHandledInterrupt}, /* trap */{0x82, NonHandledInterrupt}, /* irq0 */{0x82, NonHandledInterrupt}, /* irq1 */{0x82, NonHandledInterrupt}, /* irq2 */{0x82, NonHandledInterrupt}, /* irq3 */{0x82, NonHandledInterrupt}, /* irq4 */{0x82, NonHandledInterrupt}, /* irq5 */{0x82, NonHandledInterrupt}, /* irq6 */{0x82, NonHandledInterrupt}, /* irq7 */{0x82, NonHandledInterrupt}, /* irq8 */{0x82, NonHandledInterrupt}, /* irq9 */{0x82, NonHandledInterrupt}, /* irq10 */{0x82, NonHandledInterrupt}, /* irq11 */{0x82, NonHandledInterrupt}, /* irq12 */{0x82, NonHandledInterrupt}, /* irq13 */{0x82, NonHandledInterrupt}, /* irq14 */{0x82, NonHandledInterrupt}, /* irq15 */{0x82, NonHandledInterrupt}, /* irq16 */{0x82, NonHandledInterrupt}, /* irq17 */{0x82, NonHandledInterrupt}, /* irq18 */{0x82, NonHandledInterrupt}, /* irq19 */{0x82, NonHandledInterrupt}, /* irq20 */{0x82, NonHandledInterrupt}, /* irq21 */{0x82, NonHandledInterrupt}, /* irq22 */{0x82, NonHandledInterrupt}, /* irq23 */{0x82, NonHandledInterrupt}, /* irq24 */{0x82, NonHandledInterrupt}, /* irq25 */{0x82, NonHandledInterrupt}, /* irq26 */{0x82, NonHandledInterrupt}, /* irq27 */{0x82, NonHandledInterrupt}, /* irq28 */{0x82, NonHandledInterrupt}, /* irq29 */};(2):矩阵键盘、数码管:;描述 : 按下相应按键显示0到F中对应的数;***********************************************************/#include <stm8s105s4.h>#define uint unsigned int#define uchar unsigned charuchartable[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x8 6,0x8e};uchar num;void delay(uchar a){uchar i;for(a;a>0;a--)for(i=0;i<255;i++);}void init(void){PB_DDR=0XFF;PB_CR1=0XFF; // 将PB设置成推挽输出PC_DDR=0X1F;PC_CR1=0XFF; // 将PC设置成推挽输出PE_DDR=0x26;PE_CR1=0XFF; //将PE5,PE2,PE1为推挽输出,其他的设为上拉输入PD_DDR=0X80;PD_CR1=0X80; //将PD7设为推挽输出}/***这里的设置比LED的和数码管的设置要复杂,开始引入输入模式,矩阵键盘列为输出,行为输入,请参考协会开发板原理图及STM8转51PDF资料***//***扫描方式也可为行输出,列输入,读者可以自己尝试着修改***/uchar keys(void) //此子函数看起来很长,实则只有前面一截容,下面的“同理可得”{uchar temp;PE_ODR=0X26; //将列中的PD7置为低电平,列中的其他三个置为高电平PD_ODR=0x00;delay(40); //这里要说明一下,由于矩阵键盘第一列和AD键盘共用一个IO口//AD键盘的RC会影响IO口电平变化的时间,这里需要延时一段时间,让电容C放电完毕if((PE_IDR&0x40)==0) //如果第一列的第四行按键被按下,则进入if语句{delay(5); //延时一段时间,等待IO口电平稳定,即消抖if((PE_IDR&0x40)==0) //再次判断按键是否被按下,避免干扰{num=12; //如果第一列的第四行按键被按下,则令num=12,即数码管显示为Cwhile((PE_IDR&0x40)==0); //如果按键没有松开,则等待}}temp=PC_IDR&0xe0;if(temp!=0xe0){delay(5);temp=PC_IDR&0xe0;if(temp!=0xe0){switch(temp){case 0xc0:num=0; //如果temp的值为0xc0,则说明第1个按键被按下,下面的依次类推break;case 0xa0:num=4;break;case 0x60:num=8;break;}while((PC_IDR&0xe0)!=0xe0);}}PE_ODR=0X24;PD_ODR=0x80;if((PE_IDR&0x40)==0){num=13;delay(5);while((PE_IDR&0x40)==0);}temp=PC_IDR&0xe0;if(temp!=0xe0){delay(5);temp=PC_IDR&0xe0;if(temp!=0xe0){switch(temp){case 0xc0:num=1;break;case 0xa0:num=5;break;case 0x60:num=9;break;}while((PC_IDR&0xe0)!=0xe0);}}PE_ODR=0X22;PD_ODR=0x80;if((PE_IDR&0x40)==0){num=14;delay(5);while((PE_IDR&0x40)==0);}temp=PC_IDR&0xe0;if(temp!=0xe0){delay(5);temp=PC_IDR&0xe0;if(temp!=0xe0){switch(temp){case 0xc0:num=2;break;case 0xa0:num=6;break;case 0x60:num=10;break;}while((PC_IDR&0xe0)!=0xe0);}}PE_ODR=0X06;PD_ODR=0x80;if((PE_IDR&0x40)==0){num=15;delay(5);while((PE_IDR&0x40)==0);}temp=PC_IDR&0xe0;if(temp!=0xe0){delay(5);temp=PC_IDR&0xe0;if(temp!=0xe0){switch(temp){case 0xc0:num=3;break;case 0xa0:num=7;break;case 0x60:num=11;break;}while((PC_IDR&0xe0)!=0xe0);}}return num;}void main(){uchar n;init();while(1){n=keys(); //把函数keys()的返回值num赋给nPB_ODR=table[n];PC_ODR|=0x00; //选择第一个数码管}}中断向量:/* BASIC INTERRUPT VECTOR TABLE FOR STM8 devices* Copyright (c) 2007 STMicroelectronics*/typedef void far (*interrupt_handler_t)(void);struct interrupt_vector {unsigned char interrupt_instruction;interrupt_handler_t interrupt_handler;};far interrupt void NonHandledInterrupt (void){/* in order to detect unexpected events during development,it is remended to set a breakpoint on the following instruction */return;}extern void _stext(); /* startup routine */struct interrupt_vector const _vectab[] = {{0x82, (interrupt_handler_t)_stext}, /* reset */{0x82, NonHandledInterrupt}, /* trap */{0x82, NonHandledInterrupt}, /* irq0 */{0x82, NonHandledInterrupt}, /* irq1 */{0x82, NonHandledInterrupt}, /* irq2 */{0x82, NonHandledInterrupt}, /* irq3 */{0x82, NonHandledInterrupt}, /* irq4 */{0x82, NonHandledInterrupt}, /* irq5 */{0x82, NonHandledInterrupt}, /* irq6 */{0x82, NonHandledInterrupt}, /* irq7 */{0x82, NonHandledInterrupt}, /* irq8 */{0x82, NonHandledInterrupt}, /* irq9 */{0x82, NonHandledInterrupt}, /* irq10 */{0x82, NonHandledInterrupt}, /* irq11 */{0x82, NonHandledInterrupt}, /* irq12 */{0x82, NonHandledInterrupt}, /* irq13 */{0x82, NonHandledInterrupt}, /* irq14 */{0x82, NonHandledInterrupt}, /* irq15 */{0x82, NonHandledInterrupt}, /* irq16 */{0x82, NonHandledInterrupt}, /* irq17 */{0x82, NonHandledInterrupt}, /* irq18 */{0x82, NonHandledInterrupt}, /* irq19 */{0x82, NonHandledInterrupt}, /* irq20 */{0x82, NonHandledInterrupt}, /* irq21 */{0x82, NonHandledInterrupt}, /* irq22 */{0x82, NonHandledInterrupt}, /* irq23 */{0x82, NonHandledInterrupt}, /* irq24 */{0x82, NonHandledInterrupt}, /* irq25 */{0x82, NonHandledInterrupt}, /* irq26 */{0x82, NonHandledInterrupt}, /* irq27 */{0x82, NonHandledInterrupt}, /* irq28 */{0x82, NonHandledInterrupt}, /* irq29 */};(3);名称 :定时器的使用;描述 : 数码管显示0~F,利用定时器使得1秒变换一次;***********************************************************/#include <stm8s105s4.h>#define uint unsigned int#define uchar unsigned charuchartable[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x8 6,0x8e};uchar t;void init(void){PB_DDR=0XFF;PB_CR1=0XFF;PB_CR2=0X00;PC_DDR=0XFF;PC_CR1=0XFF;PC_CR2=0X00;TIM2_EGR=0X01; //允许产生更新事件TIM2_PSCR=0X01; //分频,使频率为1MHzTIM2_ARRH=0XC3; //更新后计数器的值TIM2_ARRL=0X50;TIM2_CR1=0X05; //允许定时器工作TIM2_IER=0X01; //允许更新中断_asm("rim"); //汇编语句,启动定时器//注意!使用定时器时要定义中断函数入口,详请打开main.c下面的stm8_interrupt_vector.c,请按照注释进行修改}void main(void){uchar i=0,j;init();while(1){PB_ODR=table[i];PC_ODR=0x02; //选择第二个数码管显示if(t==20) //这里设置50ms进入一次中断,t=20刚好为1秒{t=0; //t清零i++;if(i==16)i=0; //由于数组中只有16个数,所以i最大只能为15,否则显示会出现乱码现象}}}far interrupt void TIM2_UP_IRQHandler (void) //中断函数{TIM2_SR1 = 0x00; //进入中断时TIM2_SR1最低位会被硬件自动置一,进入中断后必须将其清零,否则无法再次产生中断t++; //进入中断后t自加1}/* BASIC INTERRUPT VECTOR TABLE FOR STM8 devices* Copyright (c) 2007 STMicroelectronics*/typedef void far (*interrupt_handler_t)(void);struct interrupt_vector {unsigned char interrupt_instruction;interrupt_handler_t interrupt_handler;};far interrupt void NonHandledInterrupt (void){/* in order to detect unexpected events during development,it is remended to set a breakpoint on the following instruction*/return;}extern void _stext(); /* startup routine */extern far interrupt void TIM2_UP_IRQHandler (void); //使用定时器要加上这句话struct interrupt_vector const _vectab[] = {{0x82, (interrupt_handler_t)_stext}, /* reset */{0x82, NonHandledInterrupt}, /* trap */{0x82, NonHandledInterrupt}, /* irq0 */{0x82, NonHandledInterrupt}, /* irq1 */{0x82, NonHandledInterrupt}, /* irq2 */{0x82, NonHandledInterrupt}, /* irq3 */{0x82, NonHandledInterrupt}, /* irq4 */{0x82, NonHandledInterrupt}, /* irq5 */{0x82, NonHandledInterrupt}, /* irq6 */{0x82, NonHandledInterrupt}, /* irq7 */{0x82, NonHandledInterrupt}, /* irq8 */{0x82, NonHandledInterrupt}, /* irq9 */{0x82, NonHandledInterrupt}, /* irq10 */{0x82, NonHandledInterrupt}, /* irq11 */{0x82, NonHandledInterrupt}, /* irq12 */{0x82, TIM2_UP_IRQHandler}, /* irq13 */ //使用定时器要把这里的“NonHandledInterrupt”改为“TIM2_UP_IRQHandler”,即中断函数名{0x82, NonHandledInterrupt}, /* irq14 */{0x82, NonHandledInterrupt}, /* irq15 */{0x82, NonHandledInterrupt}, /* irq16 */{0x82, NonHandledInterrupt}, /* irq17 */{0x82, NonHandledInterrupt}, /* irq18 */{0x82, NonHandledInterrupt}, /* irq19 */{0x82, NonHandledInterrupt}, /* irq20 */{0x82, NonHandledInterrupt}, /* irq21 */{0x82, NonHandledInterrupt}, /* irq22 */{0x82, NonHandledInterrupt}, /* irq23 */{0x82, NonHandledInterrupt}, /* irq24 */{0x82, NonHandledInterrupt}, /* irq25 */{0x82, NonHandledInterrupt}, /* irq26 */{0x82, NonHandledInterrupt}, /* irq27 */{0x82, NonHandledInterrupt}, /* irq28 */{0x82, NonHandledInterrupt}, /* irq29 */};(3)(4):蜂鸣器:定时器方式;名称 :蜂鸣器;描述 : 利用定时器产生;***********************************************************/#include <stm8s105s4.h>#define uchar unsigned char_Bool beep PD_ODR:4;uchar t2,t3;void init(void){PD_DDR=0X10;PD_CR1=0X10; //连接蜂鸣器的IO口初始化PD_CR2=0X00;PD_ODR|=0x10;TIM2_EGR=0X01; //允许产生更新事件TIM2_PSCR=0X01; //分频,使频率为1MHzTIM2_ARRH=0XC3; //更新后计数器的值TIM2_ARRL=0X50; //定时50ms,用于控制发声时间TIM2_CR1=0X05; //允许定时器工作TIM2_IER=0X01; //允许更新中断TIM3_EGR=0X01; //允许产生更新事件TIM3_PSCR=0X01; //分频,使频率为1MHzTIM3_ARRH=0X00; //更新后计数器的值TIM3_ARRL=0Xfa; //这里定时0.25ms,用于产生所需的频率TIM3_CR1=0X05; //允许定时器工作TIM3_IER=0X01; //允许更新中断_asm("rim"); //汇编语句,启动定时器}void delay(uchar s){uchar i;for(s;s>0;s--)for(i=0;i<250;i++);}void main(){init();while(1){if(t3%2==0) //前一秒产生2KHz频率的声音beep=1; //定时器3时间0.25ms,一个周期0.5ms,故频率为2Kelsebeep=0;while(t2>=20&&t2<40) //第二秒产生1KHz频率声音 {if(t3%4<2)beep=1;elsebeep=0;}while(t2>=40&&t2<60) //第三秒产生500Hz频率声音 {if(t3%8<4)beep=1;elsebeep=0;}if(t2>=60)t2=0;if(t3==8)t3=0;}}far interrupt void TIM2_UP_IRQHandler (void) //定时器2中断函数{TIM2_SR1 = 0x00; //清零TIM2_SR1 t2++;}far interrupt void TIM3_UP_IRQHandler (void) //定时器三中断函数{TIM3_SR1 = 0x00; //清零TIM2_SR1 t3++;}中断向量:/* BASIC INTERRUPT VECTOR TABLE FOR STM8 devices* Copyright (c) 2007 STMicroelectronics*/typedef void far (*interrupt_handler_t)(void);struct interrupt_vector {unsigned char interrupt_instruction;interrupt_handler_t interrupt_handler;far interrupt void NonHandledInterrupt (void){/* in order to detect unexpected events during development,it is remended to set a breakpoint on the following instruction */return;}extern void _stext(); /* startup routine */extern far interrupt void TIM2_UP_IRQHandler (void);extern far interrupt void TIM3_UP_IRQHandler (void);struct interrupt_vector const _vectab[] = {{0x82, (interrupt_handler_t)_stext}, /* reset */{0x82, NonHandledInterrupt}, /* trap */{0x82, NonHandledInterrupt}, /* irq0 */{0x82, NonHandledInterrupt}, /* irq1 */{0x82, NonHandledInterrupt}, /* irq2 */{0x82, NonHandledInterrupt}, /* irq3 */{0x82, NonHandledInterrupt}, /* irq4 */{0x82, NonHandledInterrupt}, /* irq5 */{0x82, NonHandledInterrupt}, /* irq6 */{0x82, NonHandledInterrupt}, /* irq7 */{0x82, NonHandledInterrupt}, /* irq8 */{0x82, NonHandledInterrupt}, /* irq9 */{0x82, NonHandledInterrupt}, /* irq10 */{0x82, NonHandledInterrupt}, /* irq11 */{0x82, NonHandledInterrupt}, /* irq12 */{0x82, TIM2_UP_IRQHandler}, /* irq13 */{0x82, NonHandledInterrupt}, /* irq14 */{0x82, TIM3_UP_IRQHandler}, /* irq15 */{0x82, NonHandledInterrupt}, /* irq16 */{0x82, NonHandledInterrupt}, /* irq17 */{0x82, NonHandledInterrupt}, /* irq18 */{0x82, NonHandledInterrupt}, /* irq19 */{0x82, NonHandledInterrupt}, /* irq20 */{0x82, NonHandledInterrupt}, /* irq21 */{0x82, NonHandledInterrupt}, /* irq22 */{0x82, NonHandledInterrupt}, /* irq23 */{0x82, NonHandledInterrupt}, /* irq24 */{0x82, NonHandledInterrupt}, /* irq25 */{0x82, NonHandledInterrupt}, /* irq26 */{0x82, NonHandledInterrupt}, /* irq27 */{0x82, NonHandledInterrupt}, /* irq28 */{0x82, NonHandledInterrupt}, /* irq29 */(5)蜂鸣器:stm8BEEP方式;名称:STM8自带蜂鸣器使用;描述 : ;注!此功能需用ST Link辅助设置,协会实验板无常工作,这里仅作参考;***********************************************************/#include <stm8s105s4.h>#define uchar unsigned charuchar t;void init(void) //初始化函数{CLK_ICKR|=0x08; // 打开芯片部的低速振荡器LSIwhile((CLK_ICKR&0x10)==0); // 等待振荡器稳定TIM2_EGR=0X01; //允许产生更新事件TIM2_PSCR=0X01; //分频,使频率为1MHzTIM2_ARRH=0XC3; //更新后计数器的值TIM2_ARRL=0X50;TIM2_CR1=0X05; //允许定时器工作TIM2_IER=0X01; //允许更新中断_asm("rim"); //汇编语句,启动定时器}void main(){uchar i;init();while(1){BEEP_CSR=0x26; //一秒2KHzwhile((t>=20)&&(t<40))BEEP_CSR=0x2e; //一秒1KHzwhile((t>=40)&&(t<60))BEEP_CSR=0x3e; //一秒500Hzwhile((t>=60)&&(t<80))BEEP_CSR&=0xdf; //一秒关闭if(t>=80)t=0;}}far interrupt void TIM2_UP_IRQHandler (void) //中断函数{TIM2_SR1 = 0x00;t++;}中断向量:/* BASIC INTERRUPT VECTOR TABLE FOR STM8 devices* Copyright (c) 2007 STMicroelectronics*/typedef void far (*interrupt_handler_t)(void);struct interrupt_vector {unsigned char interrupt_instruction;interrupt_handler_t interrupt_handler;};far interrupt void NonHandledInterrupt (void){/* in order to detect unexpected events during development,it is remended to set a breakpoint on the following instruction */return;}extern void _stext(); /* startup routine */extern far interrupt void TIM2_UP_IRQHandler (void);struct interrupt_vector const _vectab[] = {{0x82, (interrupt_handler_t)_stext}, /* reset */{0x82, NonHandledInterrupt}, /* trap */{0x82, NonHandledInterrupt}, /* irq0 */{0x82, NonHandledInterrupt}, /* irq1 */{0x82, NonHandledInterrupt}, /* irq2 */{0x82, NonHandledInterrupt}, /* irq3 */{0x82, NonHandledInterrupt}, /* irq4 */{0x82, NonHandledInterrupt}, /* irq5 */{0x82, NonHandledInterrupt}, /* irq6 */{0x82, NonHandledInterrupt}, /* irq7 */{0x82, NonHandledInterrupt}, /* irq8 */{0x82, NonHandledInterrupt}, /* irq9 */{0x82, NonHandledInterrupt}, /* irq10 */{0x82, NonHandledInterrupt}, /* irq11 */{0x82, NonHandledInterrupt}, /* irq12 */{0x82, TIM2_UP_IRQHandler}, /* irq13 */{0x82, NonHandledInterrupt}, /* irq14 */{0x82, NonHandledInterrupt}, /* irq15 */{0x82, NonHandledInterrupt}, /* irq16 */{0x82, NonHandledInterrupt}, /* irq17 */{0x82, NonHandledInterrupt}, /* irq18 */{0x82, NonHandledInterrupt}, /* irq19 */{0x82, NonHandledInterrupt}, /* irq20 */{0x82, NonHandledInterrupt}, /* irq21 */{0x82, NonHandledInterrupt}, /* irq22 */{0x82, NonHandledInterrupt}, /* irq23 */{0x82, NonHandledInterrupt}, /* irq24 */{0x82, NonHandledInterrupt}, /* irq25 */{0x82, NonHandledInterrupt}, /* irq26 */{0x82, NonHandledInterrupt}, /* irq27 */{0x82, NonHandledInterrupt}, /* irq28 */{0x82, NonHandledInterrupt}, /* irq29 */};/*Stm8BEEP:*//******************************************************************************** * file stm8s_beep.c* brief This file contains all the functions for the BEEP peripheral.* author STMicroelectronics - MCD Application Team* version V1.1.1* date 06/05/2009****************************************************************************** ** THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.** <h2><center>&copy; COPYRIGHT 2009 STMicroelectronics</center></h2>* image html logo.bmp****************************************************************************** *//* Includes ------------------------------------------------------------------*/ #include "stm8s_beep.h"/* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ /* Private function prototypes -----------------------------------------------*//* Private functions ---------------------------------------------------------*//* Public functions ----------------------------------------------------------*//*** addtogroup BEEP_Public_Functions* {*//*** brief Deinitializes the BEEP peripheral registers to their default reset* values.* par Parameters:* None* retval None*/void BEEP_DeInit(void){BEEP->CSR = BEEP_CSR_RESET_VALUE;}/*** brief Initializes the BEEP function according to the specified parameters. * param[in] BEEP_Frequency Frequency selection.* can be one of the values of ref BEEP_Frequency_TypeDef.* retval None* par Required preconditions:* The LS RC calibration must be performed before calling this function.*/void BEEP_Init(BEEP_Frequency_TypeDef BEEP_Frequency){/* Check parameter */assert_param(IS_BEEP_FREQUENCY_OK(BEEP_Frequency));/* Set a default calibration value if no calibration is done */if ((BEEP->CSR & BEEP_CSR_BEEPDIV) == BEEP_CSR_BEEPDIV){BEEP->CSR &= (u8)(~BEEP_CSR_BEEPDIV); /* Clear bits */BEEP->CSR |= BEEP_CALIBRATION_DEFAULT;}/* Select the output frequency */BEEP->CSR &= (u8)(~BEEP_CSR_BEEPSEL);BEEP->CSR |= (u8)(BEEP_Frequency);}/*** brief Enable or disable the BEEP function.* param[in] NewState Indicates the new state of the BEEP function.* retval None* par Required preconditions:* Initialisation of BEEP and LS RC calibration must be done before.*/void BEEP_Cmd(FunctionalState NewState){if (NewState != DISABLE){/* Enable the BEEP peripheral */BEEP->CSR |= BEEP_CSR_BEEPEN;}else{/* Disable the BEEP peripheral */BEEP->CSR &= (u8)(~BEEP_CSR_BEEPEN);}}/*** brief Update CSR register with the measured LSI frequency.* par Note on the APR calculation:* A is the integer part of LSIFreqkHz/4 and x the decimal part.* x <= A/(1+2A) is equivalent to A >= x(1+2A) and also to 4A >= 4x(1+2A) [F1] * but we know that A + x = LSIFreqkHz/4 ==> 4x = LSIFreqkHz-4A* so [F1] can be written :* 4A >= (LSIFreqkHz-4A)(1+2A)* param[in] LSIFreqHz Low Speed RC frequency measured by timer (in Hz).* retval None* par Required preconditions:* - BEEP must be disabled to avoid unwanted interrupts.*/void BEEP_LSICalibrationConfig(u32 LSIFreqHz){u16 lsifreqkhz;u16 A;/* Check parameter */assert_param(IS_LSI_FREQUENCY_OK(LSIFreqHz));lsifreqkhz = (u16)(LSIFreqHz / 1000); /* Converts value in kHz *//* Calculation of BEEPER calibration value */BEEP->CSR &= (u8)(~BEEP_CSR_BEEPDIV); /* Clear bits */A = (u16)(lsifreqkhz >> 3U); /* Division by 8, keep integer part only */if ((8U * A) >= ((lsifreqkhz - (8U * A)) * (1U + (2U * A)))){BEEP->CSR |= (u8)(A - 2U);}else{BEEP->CSR |= (u8)(A - 1U);}/* Set the AWU MR bit to load the new value to the prescalers */AWU->CSR |= AWU_CSR_MR;}/*** }*//******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/ //st visual programmer 把Option Bytes 里//AFR7改为"Port D4 Alternate Function =Beep" ,否则没有声音void main ( void ){CLK_INIT();//设置外部时钟GPIO_INIT();//初始化IOFLASH_INIT();//初始化FLASH//PD4第二功能脚不是beep功能,就强制写成beepif(FLASH_ReadOptionByte(0x4803) != 0x807F){FLASH_ProgramOptionByte(0x4803,0x80);//将PD4的第二功能脚写成beepWWDG->CR = 0x80;//复位stm8}BEEP_LSICalibrationConfig(128000);BEEP_Init(BEEP_FREQUENCY_2KHZ);BEEP_Cmd(ENABLE);while(1){delay(1000);BEEP_Cmd(ENABLE);delay(1000);BEEP_Cmd(DISABLE);}};名称 :点阵;描述 : 循环显示I LOVE(心形) U;说明:由于这里将心形采用动态形式显示,使得显示数组较多,前三个一样的数组是为了延长“I”的显示时间,这样显示时间才协调后三个数组同理,中间的九个数组是使得心形有动态效果的,这里看起来很复杂,实则读者在这里只要掌握595的使用就可以很容易理解了,595的使用涉及到操作时序,需要看懂时序图,这是很重要的;***********************************************************/#include <stm8s105s4.h>#define uchar unsigned char#define uint unsigned int_Bool E PG_ODR:0; //注意这里开始引入位定义,相当于51里的sbit E=PG0;这是stm8的位定义形式_Bool RCLK PD_ODR:4;_Bool SRCLK PD_ODR:5;_Bool SER PD_ODR:6;uchar a,b;uchar table[14][8]={{0xff,0x83,0xef,0xef,0xef,0xef,0x83,0xff},{0xff,0x83,0xef,0xef,0xef,0xef,0x83,0xff},{0xff,0x83,0xef,0xef,0xef,0xef,0x83,0xff},{0xff,0xff,0xef,0xff,0xff,0xff,0xff,0xff},{0xff,0x93,0xef,0xff,0xff,0xff,0xff,0xff},{0xff,0x93,0x6d,0xff,0xff,0xff,0xff,0xff},{0xff,0x93,0x6d,0x7d,0xff,0xff,0xff,0xff},{0xff,0x93,0x6d,0x7d,0xbb,0xff,0xff,0xff},{0xff,0x93,0x6d,0x7d,0xbb,0xd7,0xff,0xff},{0xff,0x93,0x6d,0x7d,0xbb,0xd7,0xef,0xff},{0xff,0x93,0x6d,0x7d,0xbb,0xd7,0xef,0xff},{0xff,0xbb,0xbb,0xbb,0xbb,0xbb,0xc7,0xff},{0xff,0xbb,0xbb,0xbb,0xbb,0xbb,0xc7,0xff},{0xff,0xbb,0xbb,0xbb,0xbb,0xbb,0xc7,0xff}};//存放了显示的代码void delay(uint s){uchar i;for(s;s>0;s--)for(i=0;i<200;i++);}void init(void) //初始化函数,PC是用来控制138以驱动点阵的行{PG_DDR=0x01;PG_CR1=0x01;PG_CR2=0x00;PD_DDR=0x70;PD_CR1=0x70;PD_CR2=0x00;PC_DDR=0x0f;PC_CR1=0x0f;PC_CR2=0x00;}void display(void) //显示子函数{uchar m,n,p,q;E=1; //先关闭595(赋值时会影响显示效果)m=table[a][b]; //将要显示的table[a][b]赋值给mfor(q=0;q<8;q++){p=0;if((m&0x80)==0x80)p=1; //这三句的意思是如果m的最高位是1,则p=1,否则为0,就是把m最高位赋值给pSER=p; //把p输入595输入口SRCLK=0;RCLK=1;if(1);SRCLK=1;RCLK=0; //以上语句涉及 595的操作时序,请参考595芯片资料m=(m<<1);}E=0; //赋值完后打开595}void main(){uint i,j;init();while(1){for(a=0;a<14;a++) //有14个数组要传送{for(i=0;i<10;i++) //每个数组扫描10次,这样才能看清楚{for(b=0;b<8;b++) //每个数组有8个数{display();PC_ODR=b*2; //让138和595同步delay(2); //延时一会,以使显示清楚,延时不能太长,太长会看到闪烁,也不能太短,太短显示不清楚}}}delay(1000); //为了使得看起来是I LOVE U是一个周期,这里循环一次后,延时1秒}}中断向量:/* BASIC INTERRUPT VECTOR TABLE FOR STM8 devices* Copyright (c) 2007 STMicroelectronics*/typedef void far (*interrupt_handler_t)(void);struct interrupt_vector {unsigned char interrupt_instruction;interrupt_handler_t interrupt_handler;};far interrupt void NonHandledInterrupt (void){/* in order to detect unexpected events during development,it is remended to set a breakpoint on the following instruction*/return;}extern void _stext(); /* startup routine */struct interrupt_vector const _vectab[] = {{0x82, (interrupt_handler_t)_stext}, /* reset */{0x82, NonHandledInterrupt}, /* trap */{0x82, NonHandledInterrupt}, /* irq0 */{0x82, NonHandledInterrupt}, /* irq1 */{0x82, NonHandledInterrupt}, /* irq2 */{0x82, NonHandledInterrupt}, /* irq3 */{0x82, NonHandledInterrupt}, /* irq4 */{0x82, NonHandledInterrupt}, /* irq5 */{0x82, NonHandledInterrupt}, /* irq6 */{0x82, NonHandledInterrupt}, /* irq7 */{0x82, NonHandledInterrupt}, /* irq8 */{0x82, NonHandledInterrupt}, /* irq9 */{0x82, NonHandledInterrupt}, /* irq10 */{0x82, NonHandledInterrupt}, /* irq11 */{0x82, NonHandledInterrupt}, /* irq12 */{0x82, NonHandledInterrupt}, /* irq13 */{0x82, NonHandledInterrupt}, /* irq14 */{0x82, NonHandledInterrupt}, /* irq15 */{0x82, NonHandledInterrupt}, /* irq16 */{0x82, NonHandledInterrupt}, /* irq17 */{0x82, NonHandledInterrupt}, /* irq18 */{0x82, NonHandledInterrupt}, /* irq19 */{0x82, NonHandledInterrupt}, /* irq20 */{0x82, NonHandledInterrupt}, /* irq21 */{0x82, NonHandledInterrupt}, /* irq22 */{0x82, NonHandledInterrupt}, /* irq23 */{0x82, NonHandledInterrupt}, /* irq24 */{0x82, NonHandledInterrupt}, /* irq25 */{0x82, NonHandledInterrupt}, /* irq26 */{0x82, NonHandledInterrupt}, /* irq27 */{0x82, NonHandledInterrupt}, /* irq28 */{0x82, NonHandledInterrupt}, /* irq29 */};(7):1602;名称 :1602液晶屏;描述 : 利用1602显示”today···,I am very happy,以及电协.gdutelc.,wele to LCD“;***********************************************************/#include <stm8s105s4.h>#define uchar unsigned char#define uint unsigned intuchar table0[]="today...";uchar table1[]="I am very happy!";uchar table2[]=".gdutelc.";uchar table3[]="Wele to LCD";_Bool RS PA_ODR:4;_Bool RW PA_ODR:5;_Bool E PA_ODR:6;void write_(uchar );void delay(uint a){uchar i;for(a;a>0;a--)for(i=0;i<250;i++);}void init_stm8(void){PA_DDR=0x70;PA_CR1=0x70;PA_CR2=0x00;PB_DDR=0xff;PB_CR1=0xff;PB_CR2=0x00;}void init_1602(void){write_(0x38); //显示模式设置write_(0x0c); //开显示,不显示光标write_(0x06); //地址指针自动加一write_(0x01); //清屏write_(0x80+0x04); //指针指向第一行第四格RW=0; //因只涉及向1602写数据,不涉及读,写的时候RW引脚都为低电平,故将RW置低}//写指令子函数,涉及1602时序,请参考1602资料void write_(uchar ){RS=0;E=0;PB_ODR=;delay(2);E=1;E=0;}//写数据子函数,写指令和数据区别在RS电平的高低void write_data(uchar data){RS=1;E=0;PB_ODR=data;delay(2);。

STM8S定时器2产生PWM波形

STM8S定时器2产生PWM波形
Байду номын сангаас
/*初始化自动装载寄存器,决定PWM方波的频率,Fpwm=2000000/1250=1.6Khz 定时器时钟默认为内部时钟8分频,即HSI / 8 = 2MHz*/ 5、TIM2_ARRH = 0x04; // 自动重载寄存器ARR=0x04e2=1250 6、TIM2_ARRL = 0xE2; // 每1250次产生一次中断 /*决定PWM方波的占空比 */ 7、 TIM2_CCR1H = 0x02; 8、 TIM2_CCR1L = 0x71; ARR与CCRi决定PWM的频率和占空比,当计数器工作使能以后,CNT会按照当 前频率计数,当CNT<CCRi的值时,PWM参考信号为无效电平,否则为有效电平, 有效电平为高或者为低,可通过软件在TIM2_CCERi寄存器中的CCiP位设置。当 CNT=ARR时,产生溢出,进入中断, 一个周期结束。 /* 初始化时钟分频器为1,即计数器的时钟频率为Fmaster=2Mhz */ 9、TIM2_PSCR = 0x00;//分频系数为0,不进行分频;设置分频系数 10、TIM2_IER |= 0x02;//禁止更新中断,通道1 中断允许 产生中断后需进入中断清楚标志位,否则程序会死在中断里 11、TIM2_CR1 |= 0x01;//使能计数器
TIM2产生PWM信号配置方法
脉冲宽度调制(PWM)模式可以产生一个由TIM2_ARR寄存器确定频率、由 TIM2_CCRi寄存器确定占空比的信号。 1、CLK_PCKENR1 |= 0x20; //TIM2外设时钟使能 STM8S外设时钟默认全部使能的,如果没有禁止外设时钟,此段程序可省略 2、TIM2_CR1 = 0x00;//禁止计数器 计数器一般先配置参数,最后使能 3、TIM2_CCMR1 |= 0x70; // Output mode PWM2. // 通道1被设置成比较输出方式 // OC2M = 111,为PWM模式2, // 向上计数时,若计数器小于比较值,为无效电平 // 即当计数器在0到比较值时,输出为1,否则为0 4、TIM2_CCER1 |= 0x03;/* CC polarity low,enable PWM output CC1P = 1,低电平为有效电平 CC1E = 1,开启输出引脚
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

uchar Music_Num=0,Music_Freq;
uint Music_time,PWM;
uint t=1000;
uchar Music[]={5,1,1, 5,1,1, 6,1,2, 5,1,2, 1,2,2, 7,1,4,
5,1,1, 5,1,1, 6,1,2, 5,1,2, 2,2,2, 1,2,4,
TIM2_ARRL=FREQH[Music_Freq]%256;
PWM=FREQH[Music_Freq]/8;
TIM2_CCR1H=PWM/256; //PWM占空比为%20
TIM2_CCR1L=PWM%256;
TIM3_ARRL=1000%256; //启动1S后开始播放音乐
TIM3_CR1_CEN=1; //使能定时器3
TIM3_EGR_UG=1; //允许产生更新中断
}
#pragma vector=17
__interrupt void Time3_IR_Handle(void)
//第三个数据表示节拍,即每个音调持续的时间长度
uint FREQH[]={
3823,3404,3034,2865,2551,2273,2024,
1912,1702,1517,1433,1276,1137,1012, //1,2,3,4,5,6,7,8,i
---------------------------------------------------------------*/
#incቤተ መጻሕፍቲ ባይዱude <iostm8s105c6.h>
#define uchar unsigned char
#define uint unsigned int
#define Beep PD_ODR_ODR3
/************************广东工业大学电子科技协会******************** *
* 名称:音乐播放 *
5,1,1, 5,1,1, 5,2,2, 3,2,2, 1,2,2, 7,1,2, 6,1,2,
4,2,1, 4,2,1, 3,2,2, 1,2,2, 2,2,2, 1,2,4};
//音乐数据,三个数据为一组,其中第一个数据表示音调,第二个数据表示音调高低,其中1为低8度,2为正常,3为高8度
void Time2_Init(void);
void Time3_Init(void);
void main( void )
{
Time2_Init();
Time3_Init();
asm("RIM");
while(1)
{
}
}
{
TIM3_SR1_UIF=0; //清除中断标志
TIM2_CR1_CEN=0;
Music_Freq=Music[Music_Num]+7*Music[Music_Num+1]-1; //计算音符频率
TIM2_ARRH=FREQH[Music_Freq]/256;
void Time2_Init(void)
{
TIM2_PSCR=1; //定时器频率为1MHZ
TIM2_CCMR1_OC1M=0X07; //PWM2模式
TIM2_CCER1_CC1E=1; //使能TIM2通道1输出
TIM2_CR1_CEN=1; //使能定时器
956,851,759,717,638,569,506
} ;
//音阶频率表,根据每个音调的频率(网上可查),以及定时器的频率计算出来的
}
void Time3_Init(void)
{
TIM3_PSCR_PSC=12; //2/2^11=1/2KHz,计数器为1时定时时间约2ms
TIM3_IER_UIE=1; //允许更新中断
TIM3_ARRH=1000/256;
TIM3_CR1_CEN=1;
Music_Num=Music_Num+3;
if(Music_Num>74)
Music_Num=0;
}
作者:宇辰_hong *
* 内容:采用PWM方式播放音乐 *
TIM2_CR1_CEN=1;
TIM3_CR1_CEN=0;
Music_time=Music[Music_Num+2]*128; //计算音符之间间隔时间
TIM3_ARRH=Music_time/256;
TIM3_ARRL=Music_time%256;
相关文档
最新文档