历史上的今天
今天是:2024年09月16日(星期一)
2019年09月16日 | STM8S学习03——寄存器版本的一些程序
2019-09-16 来源:eefocus
/*
一、空程序
*/
#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 _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 _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 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--); }
上一篇:Zynq篇——uart中断
下一篇:STM8S学习04——网关学习
史海拾趣
|
在设计一个9b92的板子,请问之前有人用过别的型号的usb 接口的功能么. 但作为usb device用时,是否一定要把vbus上拉。 我的板不从usb去电,是否可以通过软件在上电后启动usb口进行枚举? 因为我想省下vbus那个脚做io :-),LM的脚的复用的也太 ...… 查看全部问答> |
|
如何使用WndProc(ref Message msg) 方法?? 我的設計工具: VS2005 C# 智能設備。(windows ce 5.0)消息進行處理。在很多程序上,在msdn上也有是使用這個wndproc()方法接收消息。而且說明是windows ce 獨有的。現在我也把using Microsoft.WindowsCE.Forms; 引入了。 可是總是無 ...… 查看全部问答> |
|
那里可以下到魅族M8和宇龙酷派N90手机的原理图啊?想知道他们用的什么手机基带芯片,他们的GSM协议栈怎么实现的。 那里可以下到魅族M8和宇龙酷派N90手机的原理图啊?想知道他们用的什么手机基带芯片,他们的GSM协议栈怎么实现的。… 查看全部问答> |
|
Java 1、有电子地图开发经历、或工作流开发相关经历,没有此项经验者勿投! 2、有三年以上java开发经验,有Webservice开发相关项目经验,有良好的编程习惯,熟悉J2EE体系架构及B/S三层结构系统的开发。 3、有一定的设计能力,至少一个大中型w ...… 查看全部问答> |
|
TCHAR *szver=NULL; dwlen=GetFileVersionInfoSize(szpath[k],&dwtemp); szver=new TCHAR[dwlen]; rt1=GetFileVersionInfo(szpath[k],0,dwlen +1,szver);//这里rt1==1了 DWORD cbTranslate = 0; VerQueryValue(szver, TEXT(\"\\\\VarFileInfo\ ...… 查看全部问答> |
|
我刚上大二,对IC设计和嵌入式系统开发都有一定的兴趣,我是读电子的,同时对软件也很感兴趣,所以为了避免茫然,我想定一个长远的目标,从而更好的努力。所以我想知道这两者哪个更有前景呢,说白了就是以后出来哪个薪水相对来说会更高呢。我该如何 ...… 查看全部问答> |
|
本帖最后由 dontium 于 2015-1-23 13:24 编辑 我在ccs的例子hello时,发觉输出字符用puts()没有一点问题,但是用printf()能够编译链接通过,但是仿真运行的时候就是不行,提示下面的错误: Can\\\'t Run Target CPU: Can\\\'t write to data memory 0x ...… 查看全部问答> |




