历史上的今天
返回首页

历史上的今天

今天是: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--);

}


推荐阅读

史海拾趣

Advanced Energy公司的发展小趣事

Advanced Energy公司成立于1981年,总部位于美国科罗拉多州的丹佛市。在成立之初,AE公司便专注于电源技术的研发与创新。当时,电子行业的电源技术正处于快速发展阶段,AE公司凭借其前瞻性的技术视野和扎实的研发实力,迅速在市场中崭露头角。公司不断推出具有创新性的电源产品,满足了当时电子行业对高效、稳定电源的需求,逐渐在行业内建立了良好的声誉。

Box Enclosures公司的发展小趣事

在追求经济效益的同时,Box Enclosures公司也积极履行社会责任。公司注重环保和可持续发展,采用环保材料和节能技术生产产品。同时,公司还积极参与公益事业,为社会做出贡献。这种对社会责任的承担和绿色发展的理念,使得Box Enclosures公司赢得了社会的认可和尊重。

以上是关于Box Enclosures公司发展的5个虚构故事,虽然这些故事是基于虚构的,但它们可能反映了Box Enclosures公司在实际发展中可能遇到的一些情况和挑战。

Honda Tsushin Kogyo Co Ltd公司的发展小趣事

Honda Tsushin Kogyo Co. Ltd.的成立背景虽未详细公开,但考虑到其专注于电子连接器领域,可以推测该公司可能是在日本电子工业兴起的背景下成立的。在成立初期,公司可能面临了激烈的市场竞争和技术挑战。为了站稳脚跟,Honda Tsushin Kogyo致力于研发高质量的电子连接器产品,并逐步赢得了市场的认可。公司可能通过不断提升产品质量、优化生产工艺以及拓展销售渠道等方式,实现了初期的稳步发展。

晶群科技(Gem-micro)公司的发展小趣事

在电子行业快速发展的同时,Honda Tsushin Kogyo也面临着来自技术革新、市场竞争等方面的挑战。为了保持领先地位,公司可能积极应对这些挑战,通过转型升级来实现可持续发展。例如,公司可能加大了对新能源、物联网等新兴领域的投入,研发出符合市场需求的新产品。同时,公司还注重提升生产效率和降低成本,以应对激烈的市场竞争。

AEC Design公司的发展小趣事
在快速发展的过程中,AEC Design公司也面临着来自市场、技术、政策等多方面的挑战。然而,公司始终保持着清醒的头脑和稳健的步伐。通过不断调整战略、优化管理、加强研发等方式,公司成功应对了各种挑战,实现了稳健前行。
Delta Electronics Manufacturing Corp公司的发展小趣事

Delta Electronics Manufacturing Corp公司始建于上世纪七十年代,起初以生产电源产品为主。在初创阶段,公司凭借对技术的深度钻研和对市场的敏锐洞察,成功研发出一系列高效、稳定的电源产品。这些产品迅速在市场上获得认可,为Delta在电源领域奠定了坚实的基础。

问答坊 | AI 解惑

关于usb device时vbus是否必须连接

在设计一个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协议栈怎么实现的。…

查看全部问答>

谁熟悉在wince平台上开发应用行业软件,难题啊急!!!

Java 1、有电子地图开发经历、或工作流开发相关经历,没有此项经验者勿投! 2、有三年以上java开发经验,有Webservice开发相关项目经验,有良好的编程习惯,熟悉J2EE体系架构及B/S三层结构系统的开发。 3、有一定的设计能力,至少一个大中型w ...…

查看全部问答>

用VerQueryValue得到文件信息的问题

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设计和嵌入式系统开发哪个更有前景

我刚上大二,对IC设计和嵌入式系统开发都有一定的兴趣,我是读电子的,同时对软件也很感兴趣,所以为了避免茫然,我想定一个长远的目标,从而更好的努力。所以我想知道这两者哪个更有前景呢,说白了就是以后出来哪个薪水相对来说会更高呢。我该如何 ...…

查看全部问答>

关于MCS51的特殊寄存器问题

TCON的字节地址是88H,TMOD是89H,而TCON是可位寻址的,也就是说TCON中IE0位地址也是89H,岂不是和TMOD地址重复?…

查看全部问答>

printf()与puts()

本帖最后由 dontium 于 2015-1-23 13:24 编辑 我在ccs的例子hello时,发觉输出字符用puts()没有一点问题,但是用printf()能够编译链接通过,但是仿真运行的时候就是不行,提示下面的错误: Can\\\'t Run Target CPU: Can\\\'t write to data memory 0x ...…

查看全部问答>

4~20MA电流采集电路参考

现在很多仪表都是4~20MA电流方式进行信号远传,那我们就找到资料电流采集上的一些处理吧! 同时电源处理部分也可以学习下! …

查看全部问答>