STM8S学习03——寄存器版本的一些程序

来源:互联网 发布:安赛蜜 知乎 编辑:程序博客网 时间:2024/06/05 02:32
/*
一、空程序
*/
#include "stm8s208rb.h"
void delay(unsigned int t)
{
while(t--);
}
main()
{
PG_ODR = 0xff;
PG_DDR = 0xff;
PG_CR1 = 0xff;
PG_CR2 = 0x00;

while(1)
{
PG_ODR = 0x00;
delay(50000);
PG_ODR = oxff;
delay(50000);
}
}




/*
二、LED灯闪烁
*/
#include "stm8s208r.h"
void delay(unsigned int time);
void main(void)
{
PB_DDR |= 0X01;//选择输出模式
PB_CR1 |= 0X01;//推挽输出模式
PB_CR2 |= 0X00;//低速输出模式
while(1)
{
PB_ODR &= 0Xfe;//小灯亮
delay(50000); //调用延时函数
PB_ODR |= 0x01;//小灯灭
delay(50000); //调用延时函数
}
}
/*****************延时子程序*******************/
void delay(unsigned int time)
{
while(time--);//在此处循环
}






/*
三、跑马灯
*/
#includde "stm8s208r.h"
void delay(unsigned int time);
void main(void)
{
unsigned char i = 0;
PB_ODR = 0XFF;//设置输出寄存器的输出数值,初始化小灯全灭
PB_DDR = 0XFF;//设置I/O口B为输出
PB_CR1 = 0XFF;//设置I/O口B为推挽方式
PB_CR2 = 0X00;//输出最快速度为 2 MHZ
while(1)
{
switch(i) //让小灯从低位到高位一次亮
{
case 0: PB_ODR = 0xfe;
break;
case 1: PB_ODR = 0xfd;
break;
case 2: PB_ODR = 0xfb;
break;
case 3: PB_ODR = 0xf7;
break;
case 4: PB_ODR = 0xef;
break;
case 5: PB_ODR = 0xef;
break;
case 6: PB_ODR = 0xbf;
break;
case 7: PB_ODR = 0x7f;
break;
default: PB_ODR = 0xfe;
}
Delay(40000); //延时约20ms
i++; //让 i 加 1,下次执行程序时进入到case
if(i == 8)
{
i = 0;
}
}
}


/************延时子程序*************/
void delay(unsigned int time)
{
while(time--);
}






/*
四、数组与万能流水灯
原理:不断地将数组中的数据输出到 PB 口改变 LED 的点亮情况,从而实现 LED 的各种闪烁花样。
*/
#include "stm8s208r.h"
/********************** 定义一个二维数组 *************************/
/*******************装入使小灯花样闪烁的数据**********************/
unsigned char dis[5][8] = 
{
{0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f},
{0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe},
{0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff},
{0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01, 0x00},
{0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f}
};
/****************************函数声明*****************************/
void GPIO_Init(void); //GPIO口初始化子程序
void display(void); //用PB口显示花样小灯子程序
void delay(unsigned int time); //延时子程序
/******************************主函数*****************************/
int main(void)
{
GPIO_Init(); //端口初始化
while(1)
{
display(); //时钟让小灯显示花样
}
}
/***********************GPIO口初始化程序***************************/
void GPIO_Init(void)
{
PB_ODR = 0xff;//初始使小灯全灭
PB_DDR = 0xff;//DDR为0是输入,1为输出,此处为PB的8个端口均为输出
PB_CR1 = 0xff;//推挽输出模式
PB_CR2 = 0x00;//低速输出模式
}
/*************************小灯花样显示子程序************************/
void display(void)
{
unsigned char i, j;
for(i = 0; i < 5; i++)//循环二维数组的行数
{
for(i = 0; j < 8; j++)//循环二维数组每行中的数据
{
PB_ODR = dis[i][j];//把数据给PB口使小灯显示
delay(50000);
}
}
}
/**************************延时子程序****************************/
void delay(unsigned int time)
{
while(time--);
}




/*
五、寄存器方式实现自动切换时钟源
    接下来使用程序实现系统选择的时钟源在 HSE 和 HIS 之间来回切换,
    通过观察 LED 小灯闪烁的变化情况,并结合下面的程序理解时钟切换的设置方法
main.c 中的程序代码如下:
*/
#include<stm8s208rb.h>
_Bool LED @PG_ODR:0; //表示给 PG0 引脚取个别名 LED
void Delay(unsigned int t);
main()
{
unsigned char i;
LED = 1;
PG_DDR = 0x01;
PG_CR1 = 0x01;
PG_CR2 = 0x01;
while(1)
{
/* 判断当前时钟,如果不是HSE则切换为HSE */
if(CLK_CMSR != 0xB4)
{
/* SWEN置1,时能切换*/
CLK_SWCR |= 0x02;
/* 目标时钟源,0xB4指HSE */
CLK_SWR = 0xB4;
/* 等待,直到切换成功,SWIF被置位 */
while((CLK_SWCR & 0x08) == 0);
/* 清除标志位 */
CLK_SWCR = 0;
}
for(i = 0; i < 5; i++)
{
LED = 0;
Delay(60000);
LED = 1;
Delay(60000);
}
/* 判断当前时钟,如果不是 HSI 则切换为 HSI */
if(CLK_CMSR != 0xE1)
{
/* SWEN置1,使能切换 */
CLK_SWR = 0x02;
/* 目标时钟源,0xE1 指 HSI */
CLK_SWR = 0xE1;
/* 等待,直到切换成功,SWIF被置位 */
while((CLK_SWCR & 0x08) == 0);
/* 清除标志位 */
CLK_SWCR = 0;
}
for(i = 0; i < 5; i++)
{
LED = 0;
Delay(60000);
LED = 1;
Delay(60000);
}
}
}


void Delay(unsigned int t)
{
while(t--);
}


/*
六、库函数方式实现自动切换时钟源
    接下来使用库函数方式编写程序,重新完成时钟切换的功能。
因为工程中需要应用与 I/O 口相关的函数和与时钟相关的函数,
包含两个文件:stm8s_gpio.c/stm8s_clk.c
主函数如下:
*/
#include "stm8s.h"
void Delay(unsigned int t);
void main(void)
{
u8 i;
/* 初始化PG0,驱动LED */
GPIO_Init(GPIOG, GPIO_PIN_0, GPIO_MODE_OUT_PP_HIGH_SLOW);
while(1)
{
/* 判断当前时钟源,如果不是 HSE 则开始切换 */
if(CLK_GetSYSCLKSource() != CLK_SOURCE_HSE)
{
/* 使能自动切换,未成功则等待 */
while(CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO,
CLK_SOURCE_HSE,
DISABLE,
CLK_CURRENTCLOCKSTATE_ENABLE)
== ERROR);
}
for(i = 0; i < 10; i++)
{
GPIO_WriteReverse(GPIOG,GPIO_PIN_0);
Delay(50000);
}
if(CLK_GetSYSCLKSource() != CLK_SOURCE_HSI)
{
while(CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO,
CLK_SOURCE_HSI,
DISABLE,
CLK_CURRENTCLOCKSTATE_ENABLE)
== ERROR);
}
for(i = 0; i < 10; i++)
{
GPIO_WriteReverse(GPIOG, GPIO_PIN_0);
Delay(50000);
}
}
}
void Delay(unsigned int t)
{
while(t--);
}
#ifdef USE_FULL_ASSERT
void assert_failed(u8 *file, u32 line)
{
while(1)
{

}
}
#endif




/*
七、寄存器方式实现手动切换时钟源
    现在通过设置相应的寄存器的方式手动切换时钟源为 HSE,本例中采用中断方式,当目标时钟振荡稳定后,
切换条件成熟了,就产生中断,在中断中使能切换控制位,完成切换工作。
主函数如下:
*/
#include<stm8s208rb.h>
_Bool LED @PG_ODR:0; //表示给 PG0 引脚取个别名 LED
void Delay(unsigned int t);
main()
{
/* 使能时钟切换中断 */
CLK_SWCR |= 0x04;
/* 切换到 HSE */
CLK_SWR = 0xB4;
LED = 1;
PG_DDR = 0x01;
PG_CR1 = 0x01;
PG_CR2 = 0x00;
_asm("rim");
while(1)
{
LED ^= (_Bool)1;//LED位取反,实现小灯闪烁
Delay(50000);
}
}
void Delay(unsigned int t)
{
while(t--);
}
@far @interrupt void CLK_SW_IRQ(void)
{
/* 清除中断标志位 */
CLK_SWCR &= ~0x08;
/* 完成切换 */
CLK_SWCR |= 0x02;
}
/*
stm8_interrupt_vector.c中的程序代码如下:
*/
/*
...
extern @far @interrupt void CLK_SW_IRQ(void);
...
{0x82, CLK_SW_IRQ}, // irq2
...
*/




/*
八、库函数方式实现手动切换时钟源
现在,重新用库函数编写程序实现手动切换时钟源的任务。库函数方式需要在程序工程中
包含两个文件:stm8s_gpio.c 和 stm8s_clk.c
主函数如下:
*/
#include "stm8s.h"
void Delay(unsigned int t);
void main(void)
{
/* 初始化PG0,驱动LED */
GPIO_Init(GPIOG, GPIO_PIN_0, GPIO_MODE_OUT_PP_HIGH_SLOW);
/* 手动切换,目标时钟源为 HSE,开启中断,当亲时钟不关闭 */
CLK_ClockSwitchConfig(CLK_SWITCHMODE_MANUAL,
 CLK_SOURCE_HSE,
 ENABLE,
 CLK_CURRENTCLOCKSTATE_ENABLE);
rim();
while(1)
{

GPIO_WriteReverse(GPIOG, GPIO_PIN_0);
Delay(50000);
}
}
void Delay(unsigned int t)
{
while(t--);
}
#ifdef USE_FULL_ASSERT;
void assert_failed(u8 *file, u32 line)
{
while(1)
{

}
}
#endif
/* stm8s_it.c 中的代码如下: */
/*
...
INTERRUPT_HANDLER(CLK_IRQHandler,2)
{
//清除中断标志位
CLK_ClearITPendingBit(CLK_IT_SWIF);
//完成切换
CLK_ClockSwitchCmd(ENABLE);
}
...
*/


/*
九、PWM信号占空比测量
*/
#include<stm8s208rb.h>
unsigned long frequency;
unsigned char dutyCycle;
unsigned int captureValue1,captureValue2;
unsigned char gewei,shiwei,baiwei,qianwei,dutyCycle1,dutyCycle2;
unsigned char dis[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};


void TIM1_Init(void);
void GPIO_Init(void);
void Display(void);
void Delay(unsigned int t);


main()
{
unsigned int i;
/* 系统时钟不分频,为16MHZ */
CLK_CKDVIR = 0x00;
GPIO_Init();
TIM1_Init();
while(1)
{
/* 清除CC1IF、CC2IF标志位 */
TIM1_SR1 &= 0xf9;
/* 清除CC1OF标志位 */
TIM1_SR2 &= 0xfd;
/* 使能捕获,CC1E = 1,CC2E = 1 */
TIM1_CCER1 |= 0x11;
while((TIM1_SR1 & 0x02) == 0);
/* 等待CC2IF被置位 */
while((TIM1_SR1 & 0x04) == 0);
captureValue1 = (unsigned int)TIM_CCR2H << 8;
captureValue1 |= TIM_CCR2L;
/* 等待CC1OF被置位 */
while((TIM1_SR2 & 0x02) == 0);
captureValue2 = (unsigned int)TIM_CCR1H << 8;
captureValue2 |= TIM_CCR1L;
/* 捕获禁止 */
TIM1_CCER1 &= 0xee;
/* captureValue1/16 000 000 为测量周期,取倒为频率 */
frequency = (16000000UL/captureValue2);
/* 单位换算成kHz,小数点后 1 位 */
frequency = frequency/100;
/* captureValue1/captureValue2为占空比 */
dutyCycle = (captureValue1 * 100)/captureValue2;
/* 显示频率 */
for(i = 0; i < 400; i++)
Display();
}
}


void TIM1_Init(void)
{
/* CC1 通道被置位为输入,IC1映射在TI1FP1上,CC1S = 01 */
TIM_CCMR1 |= 0x01;
/* TI1FP1 上升沿有效,CC1P = 0 */
TIM_CCER1 &= ~(1 << 1);
/* CC2通道被置位为输入,IC2映射在TI1FP2上 CC2S = 10 */
TIM_CCMR2 |= 0x02;
/* TI1FP2下降沿有效,CC2P = 1 */
TIM_CCER1 |= (1 << 5);
/* 触发输入信号为TI1FP1, TS = 101 */
TIM_SMCR |= 0x50;
/* 触发模式为复位触发,SMS = 100 */
TIM_SMCR |= 0x04;
/* 定时器开始计数 */
TIM1_CR1 |= 0x01;
}
void GPIO_Init(void)
{
/* 数码管段选 */
PG_ODR = 0xff;
PG_DDR = 0xff;
PG_CR1 = 0xff;
PG_CR2 = 0xff;
/* 数码管选段 */
PG_ODR = 0xff;
PG_DDR = 0xff;
PG_CR1 = 0xff;
PG_CR2 = 0xff;
}
void Display(void)
{
qianwei = frequency/1000;
baiwei = (frequency % 1000)/100;
shiwei = (frquency % 100)/10;
gewei = frquency % 10;
dutyCycle1 = dutyCycle % 10;
dutyCycle2 = dutyCycle / 10;

PG_ODR = dis[gewei];
PB_ODR = 0xfe;
Delay(100);
PB_ODR = 0xff;
/* 十位亮小数点 */
PG_ODR = dis[shiwei] & 0x7f;
PB_ODR = 0xfd;
Delay(100);
PB_ODR = oxff;
PG_ODR = dis[baiwei];
PB_ODR = 0xfb;
Delay(100);
PB_ODR = 0xff;
PG_ODR = dis[qianwei];
PB_ODR = 0xf7;
Delay(100);
PB_ODR = 0xff;
PG_ODR = dis[dutyCycle2];
PB_ODR = 0x7f;
Delay(100);
PB_ODR = 0xff;
PB_ODR = dis[dutyCycle1];
PB_ODR = 0xbf;
Delay(100);
PB_ODR = oxff;
}
void Delay(unsigned int t)
{
while(t--);
}





















0 0
原创粉丝点击