stm8寄存器.docx
- 文档编号:24370124
- 上传时间:2023-05-26
- 格式:DOCX
- 页数:11
- 大小:20.67KB
stm8寄存器.docx
《stm8寄存器.docx》由会员分享,可在线阅读,更多相关《stm8寄存器.docx(11页珍藏版)》请在冰豆网上搜索。
stm8寄存器
所用芯片stm8s105s4
开发环境:
STVisualDevelop
Stm8s的库为V1.1.1
CPU频率及所有外设频率/时钟
系统复位后,所有外设时钟均处于开的状态。
用户可通过清除CLK_PCKENR1或CLK_PCKENR2中的PCKEN位来关闭相应的外设时钟。
但是在关闭外设的时钟前,用户必须设置相应的位禁用该外设。
为了使能一个外设,用户必须先设置寄存器CLK_PCKENR中对应的PCKEN位,然后设置外设控制寄存器中的外设使能位。
AWU计数器是由独立于fMASTER的内部或外部时钟(LSI或HSE)驱动,因此,即使寄存器的时钟已被关掉,该外设依然可以继续运行。
例如禁用所有外设时钟:
CLK_PCKENR1=0x00;//closeallclksofPeripheral
CLK_PCKENR2=0x00;
开启定时器TIME1定时器时钟:
CLK_PCKENR1|=0x20;//具体参考STM8S_Reference59页
CPU分频因子:
CPU时钟(fCPU)由主时钟(fMASTER)分频而来,分频因子由时钟分频寄存器(CLK_CKDIVR)中的位CPUDIV[2:
0]决定。
共7个分频因子可供选择(1至128中,2的幂)。
如图13所示。
fCPU为CPU和窗口看门狗提供时钟。
时钟分频寄存器(CLK_CKDIVR)
通用端口GPIO
和其他的单片机一样,我是习惯从端口开始学习。
Stm8s105s系列最多有7组I/O端口,A~G,而根据不同的封装可能没有其中的一些,在这里根据具体项目,我选择的是44脚封装的。
使用任何的外设前,我们都要根据需要的将参考手册和数据手册看一边,当然端口也不能另外了。
作为通用的IO口,每一个GPIO端口都有5个对应的寄存器如下表:
注意:
初始复位时,所有引脚设置为浮空输入。
地址偏移值
寄存器
7
6
5
4
3
2
1
0
0x00
Px_ODR
复位值
ODR7
0
ODR6
0
ODR5
0
ODR4
0
ODR3
0
ODR2
0
ODR1
0
ODR0
0
0x01
Px_IDR
复位值
IDR7
0
IDR6
0
IDR5
0
IDR4
0
IDR3
0
IDR2
0
IDR1
0
IDR0
0
0x02
Px_DDR
复位值
DDR7
0
DDR6
0
DDR5
0
DDR4
0
DDR3
0
DDR2
0
DDR1
0
DDR0
0
0x03
Px_CR1
复位值
C17
0
C16
0
C15
0
C14
0
C13
0
C12
0
C11
0
C10
0
0x04
Px_CR2
复位值
C27
0
C26
0
C25
0
C24
0
C23
0
C22
0
C21
0
C20
0
其中Px_ODR是ODR[7:
0]:
端口输出数据寄存器位;
(1)在输出模式下,写入寄存器的数值通过锁存器加到相应的引脚上。
读ODR寄存器,返回之前锁存的寄存器值。
(2)在输入模式下,写入ODR的值将被锁存到寄存器中,但不会改变引脚状态。
ODR寄存器在复位后总是为0。
位操作指令(BSET,BRST)可以用来设置DR寄存器来驱动相应的引脚,但不会影响到其他引脚。
Px_IDR:
IDR[7:
0]:
端口输入数据寄存器位
不论引脚是输入还是输出模式,都可以通过该寄存器读入引脚状态值。
该寄存器为只读寄存器。
0:
逻辑低电平1:
逻辑高电平
Px_DDR:
DDR[7:
0]:
数据方向寄存器位,这些位可通过软件置1或置0,选择引脚输入或输出0:
输入模式1:
输出模式
Px_CR1:
C1[7:
0]控制寄存器位
这些位可通过软件置1或置0,用来在输入或输出模式下选择不同的功能。
在输入模式时(DDR=0):
0:
浮空输入1:
:
带上拉电阻输入
在输出模式时(DDR=1):
0:
模拟开漏输出(不是真正的开漏输出)
1:
推挽输出,由CR2相应的位做输出摆率控制
Px_CR2:
C2[7:
0]控制寄存器位相应的位通过软件置1或置0,用来在输入或输出模式下选择不同的功能。
在输入模式下,由CR2相应的位使能中断。
如果该引脚无中断功能,则对该引脚无影响。
在输出模式下,置位将提高IO速度。
此功能适用O3和O4输出类型。
(参见引脚描述表)
在输入模式时(DDR=0):
0:
禁止外部中断1:
使能外部中断
在输出模式时(DDR=1):
0:
输出速度最大为2MHZ.1:
输出速度最大为10MHZ
在stm8的库里面已经将这些外设都进行了封装定义,并提供这些外设的SPI,也就是我们所说的stm8的库函数。
下面我们看看任何结构化的定义这些IO的寄存器的。
typedefstructGPIO_struct
{
vu8ODR;/*!
vu8IDR;/*! vu8DDR;/*! vu8CR1;/*! vu8CR2;/*! }GPIO_TypeDef; 所有的IO通用寄存器,定义成GPIO_TypeDef这种类型的结构体,结构体中的每个寄存器都是u8类型,这个可以查看stm8库函数类型声明,其实等价于volatieunsignedchar这种类型。 那么我们就有了GPIO_TypeDef这种类型。 下面是各个端口的结构化定义: #defineGPIOA((GPIO_TypeDef*)GPIOA_BaseAddress) #defineGPIOB((GPIO_TypeDef*)GPIOB_BaseAddress) #defineGPIOC((GPIO_TypeDef*)GPIOC_BaseAddress) #defineGPIOD((GPIO_TypeDef*)GPIOD_BaseAddress) #defineGPIOE((GPIO_TypeDef*)GPIOE_BaseAddress) #defineGPIOF((GPIO_TypeDef*)GPIOF_BaseAddress) 下面是各个端口的起始地址: #defineGPIOA_BaseAddress0x5000 #defineGPIOB_BaseAddress0x5005 #defineGPIOC_BaseAddress0x500A #defineGPIOD_BaseAddress0x500F #defineGPIOE_BaseAddress0x5014 #defineGPIOF_BaseAddress0x5019 #defineGPIOG_BaseAddress0x501E #defineGPIOH_BaseAddress0x5023 #defineGPIOI_BaseAddress0x5028 上面的部分是硬件的抽象成软件的部分,有了这些我们就可以进行对寄存器操作了,比如上面的PA_DDR的操作,现在就可以写成GPIO->DDR=VALUE; 这样进行每个端口设置时,肯定要设置使用哪个引脚,速度是多少,哪种模式,这几个对每组端口都是一样的,st有对他进行了封装,如下: typedefenum { GPIO_MODE_IN_FL_NO_IT=(u8)0b00000000,/*! GPIO_MODE_IN_PU_NO_IT=(u8)0b01000000,/*! GPIO_MODE_IN_FL_IT=(u8)0b00100000,/*! GPIO_MODE_IN_PU_IT=(u8)0b01100000,/*! GPIO_MODE_OUT_OD_LOW_FAST=(u8)0b10100000,/*! GPIO_MODE_OUT_PP_LOW_FAST=(u8)0b11100000,/*! GPIO_MODE_OUT_OD_LOW_SLOW=(u8)0b10000000,/*! GPIO_MODE_OUT_PP_LOW_SLOW=(u8)0b11000000,/*! GPIO_MODE_OUT_OD_HIZ_FAST=(u8)0b10110000,/*! GPIO_MODE_OUT_PP_HIGH_FAST=(u8)0b11110000,/*! GPIO_MODE_OUT_OD_HIZ_SLOW=(u8)0b10010000,/*! GPIO_MODE_OUT_PP_HIGH_SLOW=(u8)0b11010000/*! }GPIO_Mode_TypeDef; 具体GPIO_Mode_TypeDef;可以查看库中的GPIO.H文件中的详细定义。 看下st给出的库提供了那些操作端口的函数吧: 这些函数的详细信息可以参考st的库说明,最好去看下函数的原型代码,这样会有更好的理解。 当然了,我在使用的时候也会做一般的说明。 voidGPIO_DeInit(GPIO_TypeDef*GPIOx); voidGPIO_Init(GPIO_TypeDef*GPIOx,GPIO_Pin_TypeDefGPIO_Pin,GPIO_Mode_TypeDefGPIO_Mode); voidGPIO_Write(GPIO_TypeDef*GPIOx,u8PortVal); voidGPIO_WriteHigh(GPIO_TypeDef*GPIOx,GPIO_Pin_TypeDefPortPins); voidGPIO_WriteLow(GPIO_TypeDef*GPIOx,GPIO_Pin_TypeDefPortPins); voidGPIO_WriteReverse(GPIO_TypeDef*GPIOx,GPIO_Pin_TypeDefPortPins); u8GPIO_ReadInputData(GPIO_TypeDef*GPIOx); u8GPIO_ReadOutputData(GPIO_TypeDef*GPIOx); BitStatusGPIO_ReadInputPin(GPIO_TypeDef*GPIOx,GPIO_Pin_TypeDefGPIO_Pin); voidGPIO_ExternalPullUpConfig(GPIO_TypeDef*GPIOx,GPIO_Pin_TypeDefGPIO_Pin,FunctionalStateNewState); 介绍到这里,对通用的I/O口有个大概的了解了吧,下面我说说我自己使用的情况: 1、首先新建工程Project,将库文件GPIO.c和GPIO.h复制到该过程目录下, 2、调用st库函数初始化端口IO: /*函数名(端口PA口,端口第几个引脚PA4,PA5,PA6,IO模式推挽式输出_低电平_10M)*/ GPIO_Init(PORTA,(PIN4|PIN5|PIN6),GPIO_MODE_OUT_PP_LOW_FAST); GPIO_Init(PORTB,(PIN0|PIN1|PIN2|PIN3),GPIO_MODE_OUT_PP_HIGH_SLOW); /*函数名(端口名PB,端口第几个引脚PB0,PB1,PB2,PB3,IO模式推挽式输出_高电平_2M)*/ 这样调用函数,初始化端口完毕。 3、在控制输出时,可以调用st库函数,这里我为了快捷,是直接对输出寄存器进行操作。 如: GPIOA->ODR|=(1<<4);PA口的的第5为置高。 例如: Main() {u16i; GPIO_Init(PORTA,(PIN4|PIN5|PIN6),GPIO_MODE_OUT_PP_LOW_FAST); While (1) {GPIOA->ODR^=(1<<4);//灯闪烁 For(i=0;i<3000;i++);//延时 } } 串口通信UART Stm8微控制器家族的通用同步异步收发器(UART1,UART2或UART3)提供了一种灵活的方法与使用工业标准NRZ异步创行数据格式的外部设备之间进行全双共数据交换。 Stm8的UART提供宽范围的波特率选择,并且支持多处理器通讯。 后面关于宏定义有关的都不再介绍,详情请看st固件库,从这里开始只介绍如何使用st提供的固件库搭建自己的程序。 因为我用的芯片stm8s105s4只有UART2,所有这里直接调用固件库中的uart2.c和uart2.h就可以了。 Uart初始化函数如下: UART2_DeInit();//uart2中的个寄存器清零 /*UART1configuration------------------------------------------------------*/ /*UART1configuredasfollow: -BaudRate=9600baud -WordLength=8Bits -OneStopBit -Oddparity -Receiveandtransmitenabled//允许发送、接收 -UART1Clockdisabled*/ /*ConfiguretheUART1*/ UART2_Init((u32)9600,UART2_WORDLENGTH_8D,UART2_STOPBITS_1,UART2_PARITY_NO,UART2_SYNCMODE_CLOCK_DISABLE,UART2_MODE_TXRX_ENABLE); //*EnabletheUART1Receiveinterrupt: thisinterruptisgeneratedwhenthe //UART1receivedataregisterisnotempty UART2_ITConfig(UART2_IT_RXNE_OR,ENABLE);//开uart2接收中断 需要了解UART2_Init();可以查看uart2.c中的原型函数 这样,UART2通信已经配置好了,接下来就是使用了。 发送函数如下: voidUART2_SendData8(u8Data) {u8i; /*TransmitData*/ UART2->DR=Data; while((UART2->SR&0x40)==0);//我修改的 UART2->SR&=~(1<<6);//我修改的 } 在你需要发送数据的时候,直接调用UART2_SendData8(u8Data)就可以了。 在串口接收中断中调用读取数据函数: u8UART2_ReceiveData8(void) { return((u8)UART2->DR); } 也可以直接读取寄存器中的数据, 注意: 在中断中读完数据后,退出中断前都需要先清中断标志位,调用函数如下: UART2_ClearITPendingBit(UART2_IT_LBDF);否则中断一直存在。 ADC转换配置: ADC1和ADC2是10位的逐次比较型模拟数字转换器。 提供多达16路多功能的输入通道(实际准确的通道数量在数据手册的引脚描述说明)。 A/D转换的各通道可以执行单次和连续的转换模式。 相对与ADC2、ADC1具有一些扩展功能,包括扫描模式,带缓存的连续模式以及模拟看门狗。 请参考数据手册来了解不同型号的ADC1和ADC2的功能信息。 ADC开—关控制 通过置位ADC_CR1寄存器的ADON位来开启ADC。 当首次置位ADON位时,ADC从低功耗模式唤醒。 为了启转换必须第二次使用写指令来置位ADC_CR1寄存器的ADON位。 在转换结束时ADC会保持在上电状态,用户只需要置位ADON位来启动下次转换。 如果长时间没有使用ADC,推荐ADC切换到低功耗模式来降低功耗,这可以通过清零ADON位来实现。 当ADC模块上电后,所选通道对应的I/O输出模块是被禁用的,因此推荐在ADC上电前要选适合的ADC转换通道。 ADC时钟 ADC的时钟是由Fmaster时钟经过预分频后提供的。 时钟的预分频因子是由ADC_CR1寄存器的SPSEL[2: 0]决定的。 数据对齐 ADC_CR2寄存器中的ALIGN位于选择转换后数据的对齐方式: 右对齐: 8个低位数据被写入ADC_DL中,其余在ADC_DH中,读取时必须先读低位再读高位。 左对齐: 8个高位数据被写入ADC_DH中,其余在ADC_DL中,读取时必须先读高位再读低位。 我利用ST公司提供的固件库实验如下: 初始化如下(单次转换): voidSys_ADC1_3_Int(void) { /*InitGPIOforADC1*/ GPIO_Init(GPIOB,(GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2),GPIO_MODE_IN_FL_NO_IT);//初始化ADC端口 CLK_PeripheralClockConfig(CLK_PERIPHERAL_ADC,ENABLE); ADC1_DeInit(); //InitADC2peripheral ADC1_Init(ADC1_CONVERSIONMODE_SINGLE,ADC1_CHANNEL_0,ADC1_PRESSEL_FCPU_D2,ADC1_EXTTRIG_TIM,DISABLE,ADC1_ALIGN_RIGHT,ADC1_SCHMITTTRIG_CHANNEL0,DISABLE); //ADC1_ITConfig(ADC1_IT_EOCIE,ENABLE);//EnableEOCinterrupt只有在使用ADC中断的时候才打开这一项 /*StartConversion*/ //ADC1_StartConversion();//启动ADC转换 } 这里ADC读取分使用中断方式和不使用两种 不使用中断,启动ADC后等待转换完毕: ADC1_Init(ADC1_CONVERSIONMODE_SINGLE,ADC1_CHANNEL,ADC1_PRESSEL_FCPU_D2,ADC1_EXTTRIG_TIM,DISABLE,ADC1_ALIGN_RIGHT,ADC1_CHANNEL,DISABLE);//配置ADC通道及ADC转换模式/*数据右对齐*/ ADC1_StartConversion();//启动ADC转换/*StartConversion*/ while((ADC1->CSR&0x80)! =0x80);//等待ADC转换完毕 Adc_Value=ADC1_GetConversionValue();//读取ADC转换数据,先低位,后高位 中断方式: 在ADC中断函数中,直接读取ADC转换数据, Adc_Value=ADC1_GetConversionValue();//读取ADC转换数据,先低位,后高位 在主程序中隔一段时间选择ADC通道和启动ADC就可以了。 ADC1_Init(ADC1_CONVERSIONMODE_SINGLE,ADC1_CHANNEL_0,ADC1_PRESSEL_FCPU_D2,ADC1_EXTTRIG_TIM,DISABLE,ADC1_ALIGN_RIGHT,ADC1_SCHMITTTRIG_CHANNEL0,DISABLE); //ADC1_ITConfig(ADC1_IT_EOCIE,ENABLE);//EnableEOCinterrupt只有在使用ADC中断的时候才打开这一项
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- stm8 寄存器