STM8L相关功能配置

最近搞了搞STM8L系列的板子,感觉有些地方和S系列的不太一样,简单总结了相关外设的配置方法,相关的驱动都是可以运行的,详细内容如下
RCC时钟

 
概述:
系统时钟有四个时钟源,高速外部,高速内部,低速外部,低速内部, 上电系统默认的时钟源为高速内部时钟,时钟频率为 2M(16M/8).
HSI  :  16M 高速内部 RC 振荡器
HSE :  1-16M 高速外部晶体振荡器
LSE  :  32.768K 低速外部晶体振荡器
LSI   :  38K 低速内部振荡器
STM8L CLOCK寄存器:
时钟分频寄存器  :  CLK_CKDIVR  ( 系统时钟的分频系数设置 )
实时时钟寄存器  :  CLK_CRTCR    (RTC 时钟源及分频系数, RTC 忙状态 )
内部时钟寄存器  :  CLK_ICKCR     ( 内部时钟开关及状态 )
二个外设时钟门控寄存器  :  CLK_PCKENR1/CLK_PCKENR2 ( 相关外设的时钟开关 )
CCO 寄存器  :  CLK_CCOR  ( 时钟输出 )          
外部时钟寄存器  :  CLK_ECKCR ( 外部时钟开关及状态 )
系统时钟状态寄存器  :  CLK_SCSR ( 系统时钟源选择 )
  系统时钟切换寄存器  :  CLK_SWR ( 系统时钟源切换 )
切换控制寄存器  :  CLK_SWCR      
CSS 寄存器  :  CLK_CSSR ( 时钟安全系统 )
蜂鸣器时钟寄存器  :  CLK_CBEEPR ( 时钟源选择及切换忙状态 )
HSI 校准寄存器  :  CLK_HSICALR
HSI 时钟校准微调寄存器  :  CLK_HSITRIMR
HSI 解锁寄存器  :  CLK_HSIUNLCKR
主调节器控制状态寄存器   :   CLK_REGCSR (时钟源的开启状态)
系统时钟分频系数,默认值为 0x03(8 分频 ) ,即默认值为 2M(16M/8)

 
每个外设有相应的时钟开关,与 stm32 一样,在使用相应外设之前要打开时钟,寄存器为 CLK_PCKENR1 CLK_PCKENR2

 
 

 
时钟源选择,我们可以使用默认值选择高速内部时钟

 
 
void InitSystemClock( void )
{
    CLK_CKDIVR = 0x00;// 系统时钟分频
/* 打开全部的外设时钟*/
CLK_PCKENR1 |= 0xff;
CLK_PCKENR2 |= 0xff;
}
STM8L STM8S 的时钟部分没有太大的区别,需要注意的就是 STM8L 的外设时钟是关闭的(为了降低功耗),而 STM8S 的外设时钟是打开的,这个大家看一下相关寄存器的复位值就可以了,因此在使用 stm8l 的时候要记得打开相应的外设时钟
 
GPIO
IO 的配置比较简单, STM8L STM8S 没有什么区别,总共也就那么几个寄存器
STM8L GPIO 寄存器
一个数据方向寄存器  :  Px_DDR
一个输出数据寄存器  :  Px_ODR
一个输入寄存器  :  Px_IDR
二个控制寄存器  :  Px_CR1/Px_CR2
可选择的输入模式:浮动输入和带上拉输入
可选择的输出模式:推挽式输出
关于复用功能, IO口寄存器中没有特定的给出,我们在用到相关复用功能时,在相应外设中进行设置
 端口输出寄存器
端口输入寄存器
端口方向寄存器
 
配置 IO的时候要注意一下下面这两个寄存器,CR1主要选择输入输出的相应模式,CR2配置输出速度, 要注意一下在适应外部中断的时候,相应的 IO口的CR2要开启外部中断


 
 

 
void GPIOConfigure(void)
{
     /*LED ( 用作 pwm 呼吸灯配置输入模式 )*/
PE_DDR &= ~0X80;
  PE_CR1 |= 0X80;
PE_CR2 |= 0X00;
 
 
#if 0
     /*UART 硬件串口可以不用配置 */
     PC_DDR |= 0X08; // 输出 TX---PC3
     PC_ODR |= 0X08; // 拉高置 1
     PC_CR1 |= 0X08; // 推挽输出
     PC_CR2 |= 0X00; //10M
    
     PC_DDR &= ~0X04;  // 输入 RX---PC2
     PC_CR1 |= 0X04;   // 上拉输入
#endif
/*EXIT---PB4---PB5*/
PB_DDR &= ~0X10; // 输入
PB_CR1 |= 0X10; // 上拉输入
PB_CR2 |= 0X10; // 中断使能
 
PB_DDR &= ~0X20; // 输入
PB_CR1 |= 0X20; // 上拉输入
PB_CR2 |= 0X20; // 中断使能
 
/*PWM---TIM2_CH2*/
PB_DDR |= 0X04;
PB_CR1 |= 0X04;
PB_CR2 |= 0X04;
PB_ODR |= 0X04;
 
/*led */
PC_DDR |= 0X80; // 输出
 PC_ODR |= 0X80; // 拉高置 1
  PC_CR1 |= 0X80; // 推挽输出
  PC_CR2 |= 0X80; //10M
}
GPIO的复用功能
STM8L内部集成了控制端口复用的寄存器,不想STM8S那样需要在stvp工具中设置,这一点是很方便的,配置起来也很简单,只需要简单的几个寄存器就可以了。


 
以串口为例,串口默认的接口为PC3和PC2,我们可以执行SYSCFG_RMPCR1 |= 0X20;就可以用PC5和PC6来进行串口通讯。
void GPIO_AF(void)
{
SYSCFG_RMPCR1 |= 0X20;
}
 
定时器
概述:
STM8L15X 芯片有三种不同类型的定时器 :
          高级控制型:Timer1 ;通用型 :Timer2/3/5 ;基础型 :Timer4

 
不同的定时器功能有所差异,无非也就是输入捕获,输出比较,更新溢出,PWM 等,配置定时器必须要做的就是 (时钟分频 --- 重装载 --- 计数方式 --- 中断使能 --- 开启计数) 有其他功能就再配置其他的寄存器, PWM 要配置起模式,通道,有效电平以及占空比
相关的寄存器默认值就行很方便

 
bit7: 预装载使能
bit6: 对齐方式
bit4:   计数方向
bit0:   计数使能

 
时钟源分频系数, 3 bit ,分频值为( 1--128 2 的整数次幂)

 
 
 
重装载寄存器,发生溢出事件后自动重新装载

 
bit7:  BREAK 中断
bit6: 触发中断
bit2:   捕获比较 2
bit1: 捕获比较 2
bit0: 更新中断
定时器 2有两路PWM(捕获比较通道)
寄存器有TIMx_CCMR1和TIMx_CCMR2在输入和输出模式下配置功能也不一样,以下介绍输出模式下的配置

 
bit4--bit6   PWM 模式
bit3: 预装载
  bit0--bit1: 通道输入输出

bit4--bit5: 配置通道 2
  bit1: 有效电平
bit0: 输出使能
该寄存器集成了通道 1 和通道 2 的配置
void InitTimer2( void )
{
TIM2_CR1  |= 0x10; // 向下计数
TIM2_PSCR = 0X07; //128 分频
      
TIM2_ARRH = 0X07; // 重装载值
     TIM2_ARRL = 0XD0;
 
TIM2_CCMR2 |= 0X70; //PWM2---- 使能预装载 ---- 通道 1 输出
TIM2_CCER1 |= 0X10; // 高电平有效 ----- 通道输出使能
TIM2_CCR2H = 0X03;
TIM2_CCR2L = 0XE8;
TIM2_BKR = 0x80; // 必须加,使能通道输出
 
TIM2_CCR = (TIM2_ARRH << 8 | TIM2_ARRL);
TIM2_IER  = 0x01;  /*   允许更新中断 */
TIM2_CR1  |= 0x01;  /*   计数器使能,开始计数   */
}
需要注意的是在配置定时器2 PWM 功能时, STM8L STM8S 要多配置一个寄存器
TIM2_BKR = 0x80; // 必须加,使能通道输出
配置时也要讲相应的通道IO 进行配置,相关的时钟开关也要打开
串口
串口配置有以下几处:
数据字长,奇偶检验,停止位个数,波特率配置
使用过程中要注意相应的状态为(发送完成,接收完成等)
状态寄存器USART_SR
数据寄存器USART_DR
波特率寄存器1 USART_BRR1
波特率寄存器2 USART_BRR2
控制寄存器1 USART_CR1;
控制寄存器2 USART_CR2;
控制寄存器3 USART_CR3;
控制寄存器4 USART_CR4;
控制寄存器5 USART_CR5;
保护时间寄存器 USART_GTR
分频寄存器 USART_PSCR

bit4:   字长                     
bit2: 校验使能    
bit1: 奇偶校验     
bit0: 校验中断
 

 
  bit7: 发送空中断
bit6: 发送完成中断
bit5: 接收中断
bit3: 发送使能
bit2: 接收使能

bit4--bit5:     停止位

 
 
 
需要注意的是波特率寄存器对接收和发送是一样的,通过对 BRR1 BRR2 的编程实现。写 BRR2 应当先于写 BRR1 ,因为写 BRR1 会更新波特率计数器。
void UART_Init(void)
{
    USART1_CR1=0x00;          // 设置 M 字长, 8 位数据位
    USART1_CR2=0x2c;          // 使能发送、接收;
    USART1_CR3=0x00;         //1 位停止位
    
    USART1_BRR2=0x03;       // 设置波特率为 9600
    USART1_BRR1=0x68;
}
外部中断
关于外部中断,STM8L STM8S 的区别还是比较大的, STM8L 可以对具体的某一位开启外部中断,也可以对一组 IO 开启中断,而 STM8S 只能对一组 IO 开启中断,这也是 STM8L 低功耗的表现,相应的 STM8L 也多了几个外部中断向量,这个可以在头文件中看到。
在配置外部中断时我们首先要 CPU_CCR = 0X28;I1 I0 全部写 1 时才可以配置其他的寄存器
 
下面的程序是配置 PB4的外部中断
1 CPU_CCR I1 I0 全部写 1
2 EXTI_CR2 (配置 PB4
STM8L 提供了 EXTI_CR1 EXTI_CR2 两个寄存器来配置每组 IO 的某个位的中断边沿
EXTI_CR1 :配置每组 IO bit0---bit3
 
EXTI_CR2 :配置每组 IO bit4---bit6
 
 
 
void InitEXTI( void )
{
CPU_CCR = 0X28;
EXTI_CR2 |= 0x02;// 下降沿触发
}
 
#pragma vector = EXTI4_vector
__interrupt void EXTI1_ISR( void )
{
if(EXTI_SR1 == 0X10)// 外部中断 4 产生
{
EXTI_SR1 = 0x10;

GPIOC_BIT7_FLASH;
EXTI_FLASH = 1;
}
}
如果要配置 PB口的外部中断我们需要执行
1 EXTI_CR3 |= 0x02;// 下降沿触发
2 EXTI_CONF |= 0X02;
STM8L 提供了两个寄存器来配置每组 IO 的中断 EXTI_CR3 EXTI_CR4
EXTI_CR3 :配置端口 BDEF
 
EXTI_CR4 :配置端口 GH
 
另外要配置整组的中断,我们还需要进行中断向量的配置 EXTI_CONF
 
 
 
此寄存器的复位值为0x00 ,默认我们的 IO 口的中断向量为 EXTI0----EXTI7( 所以上面程序中我们并没有对这个寄存器操作,因为默认就是 EXTI4) ,如果要使用 EXTIA----EXTIF( 某些 IO 没有 ) 我们还需要配置此寄存器
相应的产生中断标志位的寄存器也是不一样,上面的是EXTI_SR1 ,这里是 EXTI_SR2
EXTI_SR1
 
EXTI_SR2
 
void InitEXTI( void )
{
CPU_CCR |= 0X28;
        
EXTI_CR3 |= 0x02;// 下降沿触发
EXTI_CONF |= 0X02;
}
 
#pragma vector = EXTIB_vector
__interrupt void EXTI1_ISR( void )
{
if(EXTI_SR2 == 0X01)// 外部中断 4 产生
{
EXTI_SR2 = 0x01;

GPIOC_BIT7_FLASH;
EXTI_FLASH = 1;
}
}
 
另外还要注意一点,在配置中断前关全局中断,配完相应的外设中断后,再开全局中断,这是一个标准操作,如果在外部中断配置前开全局中断,会导致 CPU_CCR 的值无法写入
配置的外部中断的IO 也要配置为输入模式,并打开 IO 口寄存器的外部中断,另外在产生中断后在中断处理函数中 EXTI_SR1 = 0x10; 要对中断标志位写 1 来清除中断标志
下面的程序配置了 PB4 PB5 ,相对应的中断向量也不同  EXTI4_vector EXTI5_vector
void InitEXTI( void )
{
CPU_CCR |= 0X28;
        
EXTI_CR2 |= 0x0a;// 下降沿触发 bit4--bit5
        
//EXTI_CR3 |= 0x02;// 下降沿触发
//EXTI_CONF |= 0X02;
}
 
#pragma vector = EXTI4_vector
__interrupt void EXTI1_ISR( void )
{
if(EXTI_SR1 == 0X10)// 外部中断 4 产生
{
EXTI_SR1 = 0x10;
GPIOC_BIT7_FLASH;
EXTI_FLASH = 1;
}
}
 
#pragma vector = EXTI5_vector
__interrupt void EXTI1_5ISR( void )
{
if(EXTI_SR1 == 0X20)// 外部中断 4 产生
{
EXTI_SR1 = 0x20;
GPIOC_BIT7_FLASH;
//EXTI_FLASH = 1;
}
}
 
AD转换
ADC 配置寄存器 1 ADC_CR1
ADC 配置寄存器 2 ADC_CR2
ADC 配置寄存器 3 ADC_CR3
ADC 状态寄存器    ADC_SR
ADC 数据高位寄存器 ADC_DRH
ADC 数据低位寄存器 ADC_DRL
ADC 高阈值高位寄存器 ADC_HTRH
ADC 高阈值低位寄存器 ADC_HTRL
ADC 低阈值高位寄存器 ADC_LTRH
ADC 低阈值低位寄存器 ADC_LTRL
ADC 通道序列寄存器 1 ADC_SQR1
ADC 通道选择扫描寄存器 2 ADC_SQR2
ADC 通道选择扫描寄存器 3 ADC_SQR3
ADC 通道选择扫描寄存器 4 ADC_SQR4
ADC 触发禁能 1-4 ADC_TRIGR1/2/3/4
具体的转换通道要看手册,开始转换后要等待几, 转换完成后,读取数据会清除相应的标志位,当不选择触发输入时,要 ADC1_SQR3 |= 0X40; // 选择扫描通道,不然无法转换
 
    bit5--bit6: 精度配置
bit4: 模拟看门狗
  bit2:   连续 / 单次
bit1: 开始
bit0: 开关
 
bit5--bit7: 采样时间
bit0--bit4: 转换通道
 
                                                    选择要扫描的通道                                                                        
unsigned intReadSTM8AD(char idx )
{
 
ADC1_CR1 |= 0X01; // 使能 ADC
ADC1_CR3 |= idx; // 选择转换通道
ADC1_SQR3 |= 0X40; // 选择扫描通道
 
 
ADC1_CR1 |= 0x02; // 开始转换;
asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
while(!(ADC1_SR & 0X01));
return ADC1_DRH;
}
EEPROM
eeprom 来说, stm8L stm8S 的寄存器配置都是一样的,只是 eeprom 的起始地址不一样,起始地址为 0x1000
 
顺序写入FLASH_DUKR=0xAE;FLASH_DUKR=0x56; 来进行解锁,
 
 
void InitEEPROM(void)
{
/* 解锁 */
do
  {
FLASH_DUKR=0xAE;
FLASH_DUKR=0x56;
}while((FLASH_IAPSR & 0x08)== 0x00);
}
 
 
unsigned char Stm8lEepromRead( unsigned char ucAddress )
{
unsigned char ucReturn;
unsigned char *p;
p = (unsigned char *)(0x1000 + ucAddress * 0x04);// 读数据
ucReturn = *p;
 
return(ucReturn);
}
 
 
void Stm8lEepromWrite( unsigned char ucAddress, unsigned char ucData )
{
unsigned char *p;
p = (unsigned char *)(0x1000 + ucAddress * 0x04);// 转换地址
*p = ucData; // 写数据
while((FLASH_IAPSR & 0x04) == 0x00); // 等待写操作完成
 
}
独立看门狗
 
IWDG_KR 用来配置开启看门狗,重装载,解锁控制命令
 
时钟源是低速内部时钟,在此寄存器中分频
 
重装载数值寄存器,在往 IWDG_KR 中写 0xAA 时重新装载喂狗
void IWDG_SetPrescaler(void)
{
IWDG_PR = 0x06;// 时钟源分频
}
 
void IWDG_SetReload(void)
{
IWDG_RLR = 0xFF;// 看门狗重装载值
}
 
void IWDG_Refresh(void)
{
IWDG_KR = (unsigned int)0xAA;// 重装载看门狗
}
 
void IWDG_Enable(void)
{
IWDG_KR = (unsigned int)0XCC;// 开启看门狗
}
 
void IWDG_Access(void)
{
IWDG_KR = (unsigned int)0X55;// 允许访问看门口狗寄存器
}
 
void IWDG_Configuration(void)
{
IWDG_Enable();
IWDG_Access();
IWDG_SetPrescaler();
IWDG_SetReload();
IWDG_Refresh();
}
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值