风驰STM8开发板例程教学
1-风驰STM8开发板简介
作者风驰QQ 779814207E-Mail 779814207@硬件平台风驰STM8开发板库版本V2.1.0非常感谢您阅读风驰STM8的学习文档,如果您在学习STM8的过程中遇到什么问题或者对我们的开发板有任何建议的话,非常欢迎您和我们一起讨论。
首先,我们想尝试着说明以下几个问题:1.为什么选择STM8作为初学者入门的首选单片机而不是51?答:风驰从以下几点来回答这个问题:1.性价比高相比于大多数入门级51开发板所选的51型号,如STC89S52、AT89C52,风驰开发板的STM8单片机—STM8S208R8要强大得多得多。
输入捕捉、输出比较、PWM、时钟控制、电源管理、AWU、SPI、I2C、CAN总线等通信接口,例如STM8S208R8的UART模块不仅有普通的串行通信功能,还有智能卡和IrDA等特有功能。
对应同样的功能,STM8S的性价比更高,普通的51单片机很难集成那么功能,而且,最重要的一点是,STM8多了这么功能,却只比一般开发板上的51单片机贵三四块钱,如此高的性价比,我们有什么理由不选择STM8呢?2.STM8更适合初学者学习市面上的51开发板的51型号的功能一般都是最简单的,单片机本身没什么太多的东西学习,所以与其说是在学单片机,不如说是在学如何操作外设。
这样子造成的结果是对结构更复杂,功能更强大的16或32位CPU的学习其实是比较不利的。
相信很多人在学了51之后打算学习32位的STM32,却发现特别不好上手。
那么,为什么说STM8更适合初学者学习呢?首先,STM8单片机功能更强更丰富,TIM1~TIM4、ADC、SPI、I2C、CAN、BEEP、UART、选项字、FLASH、AWU,两种看门狗等等功能。
对于初学者来说,选择一款功能丰富且强大的芯片作为入门的学习是非常重要。
一开始就能接触到各种功能模块的学习以及各种通信总线的应用,在学习外设的同时深入掌握CPU的结构与功能。
学习板stm8单片机篇零基础学习开发基础篇教程
图 1.3- 13 安装完成
接下来这一步很重要,就是把微云电子资料内容中>安装软件及工具>IAR FOR STM8 v1.3 里 的 config 文 件 夹 替 换 掉 C:\Program Files\IAR Systems\Embedded Workbench 6.0 Evaluation\stm8(注:个别将软件安装到别的路 径下,请自行分析替换)路径下的 config 文件夹。Config 文件夹如图 1.3- 14 所 示。如果没有这一步的话,会影响以后程序的下载。如果在安装过程中忘了这一 步,之后不用重新安装软件,直接加上这一步即可。
参考入门单片机开发板淘宝店址:
图 1.1- 2 Volume 文件夹
3、双击鼠标左键打开“Volume 文件夹”,出现安装 setup 所在文件夹,如图 1.1- 3 所示。
图 1.1- 3 setup 所在界面
4、右键单击“setup.exe”,选择以管理员身份运行,如图 1.1- 4 所示。
图 1.2- 4 选择 com 口
5、单击注册窗口右侧的蓝色圆箭头,提示输入软件注册码,如图 1.2- 5 所 示。
参考入门单片机开发板淘宝店址:
图 1.2- 5 软件注册界面
6、注意每个学习板的注册码不同,读者请参看学习板上的标签,上面就是 学习板的注册码。在灰色框内输入注册 HVGG_GQGG_JJJI_KNHM_JMJH_JKJG 如图 1.2- 6 所示,注意注册码要求英文半角大写。每四位为一组,读者以学习板 标签为主,若输入的注册码不对会有错误提示窗口。输入结束后单击蓝色箭头, 注册成功,如图 1.2- 7 Name 中的下箭头,选择 COM 口,由前面“如何在 win7 系统
STM8教程实验16-SPI总线+W25X16
例程十六SPI_Flash的读写在这个例程中我们将要了解一下SPI,SPI也是跟I2C一样也是有硬件来实现的。
SPI一般有4根线,一条时钟线CLK,2条数据线(MISO和MOSI),1条片选信号线。
如果大家想了解更多关于SPI的话,大家可以参考“STM8寄存器.pdf”文档。
里面有更详细的解释以说明。
我们平时多用到的是SPI主模式,跟I2C一样。
下面讲一下SPI主模式一些关于常见初始化和配置的知识都讲了,下面我们从主函数看起,逐步分析:SPI_FLASH_Init() SPI的初始化看看函数原型:SPI_Init()配置了数据位高位先发送,SPI 的传输的波特率为系统频率的2分频,SPI为工作在主模式,当SPI处于空闲状态时时钟线处于高电平,数据在第二个时钟传输周期被锁,数据线为全双工,使用软件方式代替使用NSS管脚,使用CRC校验。
SPI_Cmd()时能SPI设置片选信号线,先把它置高。
初始化弄好了,下面来看看怎样往从设备读写,首先是读写一个字节。
我们开发板上的从设备上W25X16的,所以我们要根据W25X16的Datasheet来配置一下参数。
这个函数就是在SPI总线上读写一个字节的操作,是根据SPI总线的时序来完成的。
可以参考数据传输过程那里的说明。
这个函数就是往W25X16的写数据的写使能,参考一下的时序准备写一个数据,参考时序往W25X16的一页写数据,每页做多能写4102Byte。
这个函数是往任何地址写任何多个Byte的数据,直到写满为止,最大2Mbyte。
这个函数是往任何地址读任何个字节的数据缓存在pBuffer中。
读W25X16的ID号,参考时序擦除一个Block的数据,参考时序:擦除整个Flash,参考时序主要的功能函数模块都讲完了,还有一些测试时候写的测试其他的函数,有兴趣的可以看下工程。
实验效果:风驰电子祝您学习愉快~~~!!!!!。
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,则跳出。
STM8教程实验2-按键扫描
STM8教程实验2-按键扫描实验二按键扫描按键扫描实际上就是对IO口的输入捕捉操作,跟LED 的刚好相反,LED 的对IO 口输出的操作,因此在操作上很相似的。
相信大家会点亮LED 的话,那么按键扫描的话也很容易了。
先看下风驰电子STM8开发板上的按键的硬件连接由电路连接图来看,如果按键按下的话,IO口读到的电平信号就是低电平。
先看看按键扫描要用到的内部资源"stm8s.h""stm8s_clk.h""stm8s_clk.c""stm8s_gpio.h""stm8s_gpio.c"首先,我们从主函数看起时钟和LED的初始话大家都清楚了,这里不多说了。
下面主要来看下按键的初始化Buttom_Init();他的函数原型很简单,对吧,就是初始话一下IO口。
上面的意思是对按键Buttom1、Buttom2、Buttom3的相应IO口初始话为上拉输入,没触发中断。
GPIO_Init(GPIOD,Buttom1|Buttom2|Buttom3,GPIO_MODE_I N_PU_NO_IT);函数原型按键的宏定义设置的模式的定义下面看看按键扫描的函数原型这个函数是当有按键按下的话就返回Buttom_ON,否则的话就返回Buttom_OFF。
他们的宏定义下面在看看另外一个函数这个函数直接是对LED的管脚的值直接取反。
GPIO_WriteReverse(GPIOD, LedPins);函数原型所以Led_Reverse(led1);是和51单片机里面的led1=~led1是一样的。
也就是对该管脚的值取反。
所以在主函数里面的的意思说Buttom1按键按一下灯LED1就会亮,再按一下,灯就会灭,不断循环。
实验现象:当你把例程下载到风驰电子STM8开发板上,你就会看到每当你按一下Buttom1(Key1),灯LED1就会亮,再按一下就会灭,如此循环。
STM8教程实验4-外部中断+按键
例程四按键中断其实在上个例程就说那个中断的,但不是重点说,例程四就重点说下这个中断的设置,主要是针对外部中断,对于其他的中断,到时在相应的模块里面会说的。
在STM8S207RB这个芯片里面有很多IO口都可以触发中断的。
主要是GPIO_A,GPIO_B,GPIO_C,GPIO_D,GPIO_E,这五组IO口都可以触发外部中断,所以大家以后要设计电路的话,必须先要查看先对应的文档来看下,了解清楚芯片的资料才好设置。
其实大家学会调用库里面的函数的话,这些初始化相当来说就很容易的了。
以上外部中断的设置来自“STM8寄存器.pdf”文档第74页下面看下电路图先吧,只要当你清楚电路具体的链接,才能完成相对应的初始化。
用到内部的资源"stm8s_clk.h""stm8s_exti.h""stm8s_gpio.h""stm8s_uart1.h""stm8s_clk.c""stm8s_exti.c""stm8s_gpio.c""stm8s_uart1.c"看完了电路图,照样是先看主函数在主函数里面最重要的是Buttom_Init();的初始化,其他的初始话上前几个例程已经有介绍过,相信大家也很清楚了。
下面重点讲下Buttom_Init()。
函数原型:第一条语句是设置Buttom1和Buttom2相对应的IO为上拉输入;第二条语句是设置GPIOD,也即是按键,为下降沿触发中断。
__enable_interrupt();这条语句是开总中断,在上一个例程里面说过了,以后凡是有触发中断的都要用上这条语句,所以说这条语句很重要的。
下面讲下外部中断常用的几个函数,这些函数都是库有的,可以直接调用的。
这个函数是设置哪组GPIO口为哪种方式触发中断的,触发方式有以下几种下降沿和顶电平触发,只有上升沿触发,只有下降沿触发,上升沿和下降沿触发这4种。
STM8教程实验26-片内EEPROM的读写
例程二十六Flash_eeprom读写实验EEPROM是单片机应用系统中经常会用到的存储器,它主要用来保存一些掉电后需要保持不变的数据。
在以前的单片机系统中,通常都是在单片机外面再扩充一个EEPROM芯片,这种方法除了增加成本外,也降低了可靠性。
现在,很多单片机的公司都推出了集成有小容量EEPROM的单片机,这样就方便了使用,降低了成本,提高了可靠性。
STM8单片机芯片内部也集成有EEPROM,容量从640字节到2K字节。
最为特色的是,在STM8单片机中,对EEPROM的访问就象常规的RAM一样,非常方便。
EEP ROM的地址空间与内存是统一编址的,地址从004000H开始,大小根据不同的芯片型号而定。
下面介绍一下STM8S了EEPROM:风驰电子STM8开发板就是大容量的了解了那么多关于STM8S 的EEPROM的知识,下面看看软件方面是如何编程的,老规矩,从主函数看起。
看到主函数,是否觉得很容易呢,在这个例程中我发了一个晚上的时间去调试,还是不行,到了第二天早上才调试成功,所以希望大家珍惜我的写的教程文档,这些教程和例程是我发了不知多少时间是总结,为了都是各位爱好者能缩短一下开发使用时间。
好了,转入正题吧,大家在做这个实验的时候要注意2个重要的地方。
第一在“stm8s_conf.h”文件中取消注释,在“stm8s.h”的文档中改成如下这样才能使用几个重要的函数。
还有一个重要的地方是,Flash_eeprom_writeread_Init()初始化一定先初始化。
下面再看看初始化的原函数这个初始化是初始化Flash正常编程方式,开启EEPROM的数据存贮器。
这是一个EEPROM的读写测试程序,EEPROM的读的话是可以每个地址每个地址的读,但是写的话必须是一个扇区一个扇区的写,每个扇区为128Byte。
至于里面的各个函数,相信大家一个就知道是什么意思了,在这里就不多说了。
里面还有一个地方要注意的,FLASH_WaitForLastOperation(FLASH_MEMTYPE_DATA);这条语句就是等待EEPROM写完成,必须的,无论EEPROM的读还是写,都必须要这条语句。
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开发板寄存器教程第五节串口UART(寄存器)
青风带你学stm8系列教程-------------寄存器操作版本出品论坛:青风电子社区作者:青风出品论坛:淘宝店:QQ技术群:371153390硬件平台:QF-STM8开发板2.5串口通信的实现2.5.1原理分析串口通信也称为异步串行通信,学过51的同学都会知道串口通信。
串口是计算机上一种非常通用设备通信的协议。
大多数计算机包含两个基于RS232的串口。
串口同时也是仪器仪表设备通用的通信协议;很多GPIB兼容的设备也带有RS-232口。
同时,串口通信协议也可以用于获取远程采集设备的数据。
串口通信的概念非常简单,串口按位(bit)发送和接收字节。
通信使用3根线完成:(1)地线,(2)发送,(3)接收。
由于串口通信是异步的,端口能够在一根线上发送数据同时在另一根线上接收数据。
其他线用于握手,但是不是必须的。
串口通信最重要的参数是波特率、数据位、停止位和奇偶校验。
对于两个进行通信的端口,这些参数必须匹配:a,波特率:这是一个衡量通信速度的参数。
它表示每秒钟传送的bit的个数。
例如300波特表示每秒钟发送300个bit。
当我们提到时钟周期时,我们就是指波特率例如如果协议需要4800波特率,那么时钟是4800Hz。
这意味着串口通信在数据线上的采样率为4800Hz。
通常电话线的波特率为14400,28800和36600。
波特率可以远远大于这些值,但是波特率和距离成反比。
高波特率常常用于放置的很近的仪器间的通信,波特率除数(baud-rate divisor)是一个22位数,它由16位整数和6位小数组成。
波特率发生器使用这两个值组成的数字来决定位周期。
通过带有小数波特率的除法器,在足够高的系统时钟速率下,UART可以产生所有标准的波特率,而误差很小。
波特率除数公式:BRD=BRDI.BRDF=SystemClock/(16×BaudRate)其中:BRD是22位的波特率除数,由16位整数和6位小数组成BRDI是BRD的整数部分BRDF是BRD的小数部分SystemClock是系统时钟(UART模块的时钟直接来自SystemClock)BaudRate是波特率(9600,38400,115200等)b,数据位:这是衡量通信中实际数据位的参数。
STM8教程实验11-ADC模数转换
例程十一 ADC及其应用在计算机过程控制的数据采集等系统中,经常要对一些过程参数进行测量和控制,这些参数往往是连续变化的物理量,如温度,压力,流量和速度等。
这里所指的连续变化即数值是随着时间连续可变的,通常称这些物理量为模拟量,然而计算机本身所能识别和处理的都是数字量。
这些模拟量在进入计算机之前必须转换成二进制数码表示的数字信号。
能够把模拟量变成数字量的器件称之为模数转换器。
15.1 STM8S207ADC模块概述(注STM8S207系列高性能产品包括了一个10位连续渐进式模数转换器ADC2,意STM8S2XX都没有ADC1)提供了多达16个多功能的输入通道。
主要性能有: 转换时间为14个时钟周期,带有参考电压引脚,可设置为单次或联系的转换模式,可设置转换结束产生中断。
15.2 ATD模块接口组成和特点STM8S207单片机内置的ADC模块如下图所示:ADC模块可以通过ADC_CR1寄存器来开启或者关闭。
然后ADC的时钟是有f_master时钟经过预分频后提供的。
STM8S207高达16个输入通道,支持多种转换模式15.3 ADC模块寄存器设置STM8S207的ADC模块共有8个寄存器。
分为4个设置寄存器,2个数据寄存器和2个施密特触发禁止寄存器。
15.3.1 ADC控制/状态寄存器ADC_CSREOC:转换结束。
此位在AD转换结束后由硬件置位。
由软件写“0”来清零 0:转换未结束1:转换结束AWD:因为STM8S207没有ADC1,所以此位无效EOCIE:转换结束EOC的中断使能0:禁止转换结束中断1:使能转换结束中断AWDIE:在STM8S207中无效位CH:选择转换通道,分别选择0到15共16个通道15.3.2 ADC配置寄存器1 ADC_CR1SPSEL:预分频选择位000:f_adc = f_master/2001:f_adc = f_master/3010:f_adc = f_master/4011:f_adc = f_master/6100:f_adc = f_master/8101:f_adc = f_master/10110:f_adc = f_master/12111:f_adc = f_master/18CONT:连续转换0:单次转换模式1:连续转换模式ADON:AD转换开关0:禁止ADC转换,进入低功耗模式1:使能ADC并开始转换需要注意的是:如果此位是0时,并且写1到此位,那么将把ADC从低功耗模式下唤醒。
stm8教程实验11adc模数转换
例程十一 ADC及其应用在计算机过程控制的数据采集等系统中,经常要对一些过程参数进行测量和控制,这些参数往往是连续变化的物理量,如温度,压力,流量和速度等。
这里所指的连续变化即数值是随着时间连续可变的,通常称这些物理量为模拟量,然而计算机本身所能识别和处理的都是数字量。
这些模拟量在进入计算机之前必须转换成二进制数码表示的数字信号。
能够把模拟量变成数字量的器件称之为模数转换器。
15.1 STM8S207ADC模块概述(注STM8S207系列高性能产品包括了一个10位连续渐进式模数转换器ADC2,意STM8S2XX都没有ADC1)提供了多达16个多功能的输入通道。
主要性能有: 转换时间为14个时钟周期,带有参考电压引脚,可设置为单次或联系的转换模式,可设置转换结束产生中断。
15.2 ATD模块接口组成和特点STM8S207单片机内置的ADC模块如下图所示:ADC模块可以通过ADC_CR1寄存器来开启或者关闭。
然后ADC的时钟是有f_master时钟经过预分频后提供的。
STM8S207高达16个输入通道,支持多种转换模式15.3 ADC模块寄存器设置STM8S207的ADC模块共有8个寄存器。
分为4个设置寄存器,2个数据寄存器和2个施密特触发禁止寄存器。
15.3.1 ADC控制/状态寄存器ADC_CSREOC:转换结束。
此位在AD转换结束后由硬件置位。
由软件写“0”来清零 0:转换未结束1:转换结束AWD:因为STM8S207没有ADC1,所以此位无效EOCIE:转换结束EOC的中断使能0:禁止转换结束中断1:使能转换结束中断AWDIE:在STM8S207中无效位CH:选择转换通道,分别选择0到15共16个通道15.3.2 ADC配置寄存器1 ADC_CR1SPSEL:预分频选择位000:f_adc = f_master/2001:f_adc = f_master/3010:f_adc = f_master/4011:f_adc = f_master/6100:f_adc = f_master/8101:f_adc = f_master/10110:f_adc = f_master/12111:f_adc = f_master/18CONT:连续转换0:单次转换模式1:连续转换模式ADON:AD转换开关0:禁止ADC转换,进入低功耗模式1:使能ADC并开始转换需要注意的是:如果此位是0时,并且写1到此位,那么将把ADC从低功耗模式下唤醒。
STM8教程实验21-SPI总线+SD卡+block的读写
STM8教程实验21-SPI总线+SD卡+block的读写例程⼆⼗⼀SDCard基于SPI总线的读写SDCard现在可以说是⾮常流⾏的了,⽆论是⼿机,相机等等的电⼦产品中都能见到它的影⼦,所以对于SDCard的读写就变得⼗分之重要了,SDCard有2中链接⽅法,⼀种是SPI,另⼀种是SDIO。
2种链接⽅式的读写速度相差很⼤的,基于SPI的读写只要25Mbit/s,⽽基于SDIO⽅式便可以达到100Mbit/s。
在我的STM8开发板上没有SDIO的总线,那只能是基于SPI总线的读写。
那我们先看看它的链接⽅式吧这就SPI总线的接法。
SDCard涉及的知识⾮常多,如果要具体到每⼀点去讲解的话,恐怕要将⼏天都讲不完,下⾯我主要讲⼀下简单实⽤,并且是在单⽚机的应⽤,其他的就留给读写再深⼊去了解。
SDCard每个扇区⼤约有10万次的写寿命,读的话就没有限制,这应该够我们的吧。
擦除操作可以加速写操作,因为在写之前会进⾏擦除操作。
如果SDCard不在⽀持的电压范围内,他是忽略所有总线的传输。
SD卡总线采⽤的是单主多从结构,总线上所有卡公⽤时钟和电源线。
主机可以通过不同的⽚选信号线依次分别访问每个卡,每个卡的CID寄存器中已预编程了⼀个唯⼀的卡标识号,来区分不同的卡,主机通过READ_CID的命令读取CID寄存器,CID寄存器咋SD卡⽣产过程中的测试和格式化是被编程,主机只能读取改号。
SD的读写操作有2种Single Block Mode 和Multiple Block Mode。
Single Block Mode :主机根据事先定义的长度读写⼀个数据块。
有发送模块⽣成⼀个16位的CRC校验码,接受端根据校验码进⾏检验。
读操作的块的长度受设备sector⼤⼩(512byte)的限制,但是可以最⼩为⼀个字节。
不对齐的访问时不允许的,每个数据块必须位于单个物理sector内。
写操作的⼤⼩必须为sector ⼤⼩,起始地址必须与sector边界对齐。
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 recommended 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 recommended 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 recommended 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 recommended 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 recommended 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>© 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 recommended 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,以及电协www.gdutelc.,welcome 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[]="Welcome 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;。
STM8S208开发板用户手册V1.20
1简介。
顺哥STM8开发板是一款基于STM8系列单片机的开发板,班上固有的外设可以完成CAN总线串口通信,电容触摸按键和电容触摸划块实验,可以完成相应的实验。
本文档只是对板子的简单使用做了简单的说明,并且对板子的几个程序进行了简要的说明2开发板的简介2.1开发板布局(/item.htm?id=133********)2.2板子跟仿真器的链接2.2.1ST LINK III仿真器简介(/item.htm?id=12415784614)ST-LINK III仿真器是ST意法半导体为初学者学习、评估、开发STM32系列ARM MCU设计的仿真开发工具。
ST-LINK II配合IAR Systems EWARM集成开发环境,是STM32系列初学者学习入门、软件编程调试的最佳开发工具。
2.2.2仿真器的特点支持全系列STM32/STM8S系列MCU,USB2.0全速,·下载速度大于20Kb/秒自适应目标系统JTAG电平3.3V-5V标准20芯JTAG仿真插座.与其他的仿真器相比,ST link III,非常方便,无需单独安装设备驱动,即插即用。
不足的是仿真器的速度不高。
2.2.3仿真器与顺哥STM8S208开发板的连接在正常的链接之后拔掉下载选择跳线帽可以进行仿真2.2.4硬件仿真在仿真器跟板子连接之后,我们打开编译软件STVD在程序编译通过之后,设置编译器然后点击“Debug”按键可以观察到仿真器上面的小灯,闪烁,正常的进行仿真。
2.2.5仿真处理当我们第一次用仿真器向STM8S208RB的单片机烧写某些程序的时候会出现下图所示的错误这是由于没有烧写过程序的STM8S208RB单片机里面的USB区域的一部分是写保护的,只要将UBC区域的写保护去除即可,如图正是由于UBC的部分区域被保护,所以STM8S208RB单片机的程序串口下载跟其他的STM8系列单片机有所不同。
2.3串口下载大多数的单片机可以进行串口下载,STM8S系列单片机也不例外,也可以进行串口下载,使用软件flash Loader Demo在STM8S208RB单片机的在没有进行UBC区域解锁的时候,是没有办发进行程序下载的,即使能够进入程序下载界面也没有办法将程序烧如单片机,所以下面进行的操作是在UBC区域解锁之后.,并且使用顺哥的STM8S208开发板时的设置,其他的板子和单片机型号不可。
STM8教程实验22-SPI总线+SD卡+系统文件的读写
2/5
风驰电子 STM8 开发板
2011
一般最常用的就是这几个函数,其实大家看了它的英文注释也大概了解到这 个函数的意思了吧。大家结合例程中的例子进行简单的分析下。 f_mount(0, &myfs[0]); 在文件系统注册一个工作区, 这个工作区的设备号为 0, 相对于盘符的意思, 这个参数开设为 0~9, &myfs[0]是指向工作区的指针。 一般定义 myfs 为 FATFS 类型,这个 FATFS 是个结构体类型的。 f_open( &myfsrc , "0:/My__Demo.TXT" , FA_CREATE_NEW | FA_WRITE);这个函 数的意思是在刚刚开辟盘符 0 下一个以只写的方式打开文件名为 My__Demo.TXT 的文件, 如果该文件不存在, 就新建一个名为 My__Demo.TXT。 该文件是关联到 myfsrc 这个结构体指针的,在之后的文件读写都是通过该结 构体去完成的。 myres = f_write(&myfsrc, mystring, sizeof(mystring), &mybr);这个函数就要把你 要写的信息写进刚才创建或打开的 My__Demo.TXT 中。 f_close(&myfsrc); 关闭文件。 f_read( &myfsrc, save_buffer, sizeof(save_buffer), &mybr );这个函数就是从已经 打开的文件里读出数据放在 save_buffer。 但是从应用层方面来说,会运用上面所说那几个函数就可以了,会使用这几 个函数就会了对系统文件的读写,就可以做更多东西了,接下那 2 讲的教程 就是要用到这几个函数对系统文件的读写。我们期待着下 2 讲教程。 下面就是看看主函数
STM8教程-第二章 快速体验--目标板
第二章快速体验-----目标板在开发嵌入式系统时,通常需要选择一款满足开发要求的开发板(也称为目标板),作为开发和测试的原型系统。
本章将为读者简要介绍基于STM8S207 嵌入式微控制器的开发板结构,以及如何通过Flash Loader Demo 下载程序到开发板上进行测试和使用。
2.1 目标板结构如下图所示为STM8S07 开发板的硬件结构图,其中MCU 是ST 公司生产的STM8S207,芯片配置存储容量较大的6KB 的RAM 和128K 的闪存(Flash)。
芯片内部资源非产丰富,包括2KB 的EEPROM、10 位精度的ADC、1 个高级控制定时器、2 个16 位通用定时器和1 个8 位基本定时器、2 个UART、SPI、IIC 以及带有指定选择频率的BEEP 接口。
目标板资源也非常丰富,包括SD 卡接口、串口(UART)接口(已经转换为USB 接口,方便使用)、IIC 接口、SPI 接口以及全部IO 口引接出来、24C02 数据存储、W25X16 数据存储、2.6 寸TFT 触摸屏接口。
2.2 STM8S207 初体验在了解开发板的基本结构以后,读者肯定在想,如何使用这样一块板子呢?如何才能有效地控制板子上的芯片呢?这是一个很自然的问题。
下面的内容就是介绍如何利用开发板搭建起嵌入式系统开发平台环境,希望读者能够对STM8S207 开发有一个最初的体验。
2.2.1 安装Flash Loader DemoFlash Loader Demo 是ST 公司发布的一款支持串行下载程序的软件。
该软件支持擦除、下载、读取操作。
其中下载擦除支持选择擦除必要页、不擦除或者全部擦除其中一项。
当然不是所有芯片都支持Flash Loader Demo 下载的,而且第一次下载的程序没有用修改optionbyte 使得Bootloader enable。
串口下载步骤:1、先插上USB 供电再打开Flash Loader Demo 软件。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
工程模板的创建在开发STM8的时候,首先要学会创建一个工程模板,所有的开发历程都是基于这个工程模板。
STM8有官方库,在开发的时候很方便,可以远离查寄存器的时代。
学过51单片机或者AVR的人都知道,查寄存器是很不方便的。
现在带大家进入一个利用库来开发单片机的新时代。
本开发板的所有例程都是基于库V2.0.0版本。
STM8的编译器是IAR Embedded Workbench。
下面叫大家如果去创建一个过程模板工程模板创建步骤:1、双击,打开IAR的界面,点击File->New->Workspace,点击Project->Create New Project,出现点击OK就行。
2、右击工程名就可以添加文件夹和文件,3、4、设置工程的Options,右击工程名->Options,设置其中两项,如下图5、在这里设置Device 为STM8S207RB 因为在我们风驰电子STM8开发板的主控芯片是STM8S207RB这里是设置编译路径,使用了3条语句$PROJ_DIR$\..\FWlib\inc$PROJ_DIR$\..\FWlib\src$PROJ_DIR$\..\USER$PROJ_DIR$\..意思是找到当前工程的上一级$PROJ_DIR$\..\FWlib\inc意思是先找到当前工程的上一级FWlib文件夹,再找到inc文件夹$PROJ_DIR$\.意思是当前文件夹这里是设置输出文件为可执行文件此外,我们还有修改一下头文件在stm8s.h的头文件修改#define STM8S207 /*!< STM8S High density devices without CAN */在stm8s_conf.h的头文件里修改你要用到的头文件,不要用到的资源的头文件可以把它注释调就可以,方便使用,到这里,相信大家都体会到用库的方便性了吧。
到这里 ,点击就可以编译成功了。
当你看到这里的话相信你会了怎样创建一个工程了。
下面看STM8的一些主要的初始化,最重要的一点的是时钟的初始化。
其实STM8你不设置时钟也可以运行的,因为STM8单片机复位它就默认为内部时钟的8分频。
所以我们要设置时钟,STM8S可以设置外部时钟,也可以设置内部时钟,在这里我们的就设置内部高速时钟16M,要不然的话,你一旦复位,就只有内部16M晶振的8分频。
工程模板里面使用的资源:“stm8s_clk.h”“stm8s.h”“stm8s_clk.c”下面直接看下我们的主函数CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1); 配置内部高速时钟,就是16M 的内部时钟void CLK_HSIPrescalerConfig(CLK_Prescaler_TypeDef HSIPrescaler)函数原型分频设置是个枚举来的时钟的设置可以参考STM8寄存器.pdf的图13 时钟树风驰电子祝您学习愉快~~~!!!!!例程一流水灯流水灯实验是每个电子爱好者学任何一款单片机必备先学会的一个实验,因为流水灯的操作就是简单的对IO口的直接操作,是初学者最喜欢的一个实验,但你会了点亮一个灯的时候,证明了你对这款单片机有了初步的了解和初步的操作,以后那个模块就相当来说就好办了。
下面介绍下在风驰电子STM8开发板实现流水灯操作要用到的资源这是开发板上的电路连接图。
只要给PD0、PD1、PD2、PD3任何一个低电平,灯就会亮了。
流水灯要用到的内部资源"stm8s_clk.h""stm8s_clk.c""stm8s_gpio.h""stm8s_gpio.c""stm8s.h"好了,我们先看下主函数这里是一些初始化,CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);/*!<Set High speed internal clock */这个就是切换到外部时钟的函数,这个函数在STM8S工程模板的文档说得很详细了,在这里就不多说了。
LED_Init();LED 的一些初始化,必须要初始化这个函数,否则,LED就不能正常工作了,下面的LED_Init()函数原型这个函数的意思是定义LED 灯的的管脚位PD0、PD1、PD2、PD3为推挽输出/*!< Output push-pull, high level, 10MHz */相应的管脚模式是可以选择的,在stm8s_gpio.h 的文件里面有相应的定义在LED_ShowOneToOne();中实现了单个LED的点亮或熄灭函数原型LED1(ON)这个是宏定义来实现的,这样看起来就简单明了。
我们再看看宏定义我们再看看在STM8里面也可以直接对每个IO口置1或写0,跟51单片机一样的,主要在下面这两个函数实现,先看下他们的函数原型在这个函数中,只有你配置好是哪个IO口,他就会相对于的该IO口设为0,即是低电平。
在我们的例程其中一个的话就是设置参数GPIOD,GPIO_PIN_0,就好象51里面的P3_0=0;操作起来就好像51的一样的操作。
同样这个就是给IO口置1,也就是置高电平。
大家再看看下面的函数就是实现函数原型这个函数写得有点复杂,是因为为了让LED在风驰电子STM8开发板按顺序的流起来。
主要看下这条语句就可以了这条语句的让第几盏灯亮,当PortVal=0的话就是我们开发板上的LED0亮。
在这里用左移操作符<<和取反操作符~。
相信看过C语言的知道是什么意思了,在这里不多说了。
还有一个函数大家需要知道的这个函数就是直接对某个端口的8位直接赋值。
看看它的函数原型但大家看到这里的话,相信大家对IO的操作就不在话下了。
好的,对IO口的操作就分析到这里。
实验现象当大家把我的例程下载到风驰电子STM8开发板就可以看到流水灯按照一定的频率兜圈不断的跑风驰电子祝您学习愉快~~~实验二 按键扫描按键扫描实际上就是对IO口的输入捕捉操作,跟LED 的刚好相反,LED 的对IO 口输出的操作,因此在操作上很相似的。
相信大家会点亮LED 的话,那么按键扫描的话也很容易了。
先看下风驰电子STM8开发板上的按键的硬件连接由电路连接图来看,如果按键按下的话,IO口读到的电平信号就是低电平。
先看看按键扫描要用到的内部资源"stm8s.h""stm8s_clk.h""stm8s_clk.c""stm8s_gpio.h""stm8s_gpio.c"首先,我们从主函数看起时钟和LED的初始话大家都清楚了,这里不多说了。
下面主要来看下按键的初始化Buttom_Init();他的函数原型很简单,对吧,就是初始话一下IO口。
上面的意思是对按键Buttom1、Buttom2、Buttom3的相应IO口初始话为上拉输入,没触发中断。
GPIO_Init(GPIOD,Buttom1|Buttom2|Buttom3,GPIO_MODE_IN_PU_NO_IT);函数原型按键的宏定义设置的模式的定义下面看看按键扫描的函数原型这个函数是当有按键按下的话就返回Buttom_ON,否则的话就返回Buttom_OFF。
他们的宏定义下面在看看另外一个函数这个函数直接是对LED的管脚的值直接取反。
GPIO_WriteReverse(GPIOD, LedPins);函数原型所以Led_Reverse(led1);是和51单片机里面的led1=~led1是一样的。
也就是对该管脚的值取反。
所以在主函数里面的的意思说Buttom1按键按一下灯LED1就会亮,再按一下,灯就会灭,不断循环。
实验现象:当你把例程下载到风驰电子STM8开发板上,你就会看到每当你按一下Buttom1(Key1),灯LED1就会亮,再按一下就会灭,如此循环。
风驰电子祝您学习愉快~~~例程三串口通信学玩前面两个例程之后,是否觉得STM8S操作起来也很简单吧,其实是的。
在这个例程我要讲下串口通信的设置和用法。
但我们学一款新的单片机,必须要做到这样的步骤,第一会点亮LED,第二会按键扫描,第三就是要会串口通信。
为什么呢要这样的安排呢?会LED和按键扫描的就是学会的IO口的输出与输入,这是最基本的,但学会这两个的话,就要学串口通信,因为串口通信对其他模块的调式是会有很大的帮助,可以这样说必须的。
这些当你接触到你就会知道的了。
好的,下面看下我们风驰电子STM8开发板的串口通信的原理图吧。
我们的板子上以利用PL2303来下载程序和串口通信,只要大家按照上面的链接的话就可以了。
这里我只是把重要的截图给大家看而已,大家可以参考我们的风驰电子STM8S开发板原理图.pdf文件的要用到内部资源:"stm8s_clk.h""stm8s_uart1.h""stm8s_clk.c""stm8s_uart1.c"好的,我们先看我们的主程序时钟的初始化在前面都有说了,这里就不说了,下面主要来看一下串口的初始化Uart_Init();。
该函数的原型在这个例程是设置波特率为115200,8位数据位,1位停止位,没有奇偶校验,查询方式发送,中断方式接收。
Uart1 的时钟是关闭的。
下面,在看看几个重要的函数:这个函数是发送一个字节,查询发送。
当发送寄存器是空的就发送。
这个函数是把一个字节写进发送寄存器。
这个函数是获得标志的一个函数,在这里的参数是选择是发送寄存器标志。
这两个函数是库自带的,直接调用过来的。
所以说基于库开发STM8是挺快的,不用直接操作寄存器。
直接调用库里面的函数。
这个就是各种标志位参数,如果大家想查询哪个标志位的是什么状态的话就可以调用这个函数和这些标志参数,在库里面会有各种子函数,都是官方封装好的,用起来挺方便的,是不是学起来比51单片机和AVR方便多了。
这个函数是发送字符串的,包括英文和中文的字符串。
这个是函数是利用查询方法来接收一个字节,用查询方法来接收一个字节的话,会限制CPU的利用率,因为CPU要等到接收到了数据才释放,这样对于开发利用不好,所以还是提倡中断接收,这样会有效的利益CPU。
查询的话,也是查询接收寄存器,如果是RXNE==RESET的话就表明可以接受这个数据了。
下面重点介绍一下中断服务函数的写法。
在我们例程中我把所有中断函数都列出来,只要大家添加“stm8s_interrupt.c”这个文件就可以,大家可以在相应的位置添加自己的代码就可以了。
下面介绍一下接收中断服务函数:接收中断函数的中断号是0x14。