/* Includes ------------------------------------------------------------------*/
#include "user.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
static void TIM1_PWM_Config(void);
static void TIM4_Config(void);
static void GPIO_Config(void);
static void UART1_Config(void);
static void ADC_Config(void);
static void IWDG_Config(void);
static void WWDG_Config(void);
static void IT_Config(void);
/* Public functions ----------------------------------------------------------*/
void CLK_Config(void)
{
//配置内部16M时钟作为时钟源
//CLK_ICKR_HSIEN = 1; //使能内部高速时钟(复位值)
CLK_ICKR_bit.LSIEN = 1; //使能内部低速时钟
CLK_CKDIVR_bit.HSIDIV = 0; //主时钟分频 0-3对应 1 2 4 8分频
CLK_CKDIVR_bit.CPUDIV = 0; //CPU时钟分频 0-7对应 1 2 4 8 16 32 64 128分频
//CLK_SWR = 0xE1; //HSI为主时钟源(复位值)
//CLK_SWCR_SWEN = 1; //使能自动切换时钟
//CLK_SWR = 0xD2; //0xD2:LSI为主时钟源(仅当LSI_EN选项位为1时)
//CLK_SWR = 0xB4; //0xB4:HSE为主时钟源
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
//外设时钟控制寄存器 CLK_PCKENR1
// CLK_PCKENR1 = 0x00; //复位值为0xff,即默认为开启状态
// PCKEN10: I2C
// PCKEN11: SPI
// PCKEN12: UART1
// PCKEN13: UART2/3 实测此位才是UART1时钟使能(stm8s103f3)
// PCKEN14: TIM4
// PCKEN15: TIM2
// PCKEN16: TIM3
// PCKEN17: TIM1
CLK_PCKENR1 = b10011000; //使能TIM1,TIM4,UART1 时钟
//外设时钟控制寄存器 CLK_PCKENR2
// CLK_PCKENR2 = 0x00; //复位值为0xff,即默认为开启状态
// PCKEN20: Reserved
// PCKEN21: Reserved
// PCKEN22: AWU
// PCKEN23: ADC
// PCKEN24: Reserved
// PCKEN25: Reserved
// PCKEN26: Reserved
// PCKEN27: CAN
CLK_PCKENR2 = b00001000; //使能 ADC 时钟,
//LK_CSSR_CSSEN = 1; //使能时钟监控功能,外间时钟出问题时切换到内部时钟源HSI/8 CLK_CSSR中的CSSD位被置位
//LK_CCOR = ; //时钟输出寄存器
}
void Peripherals_Config(void)
{
GPIO_Config();
TIM1_PWM_Config();
TIM4_Config();
UART1_Config();
ADC_Config();
IWDG_Config();
WWDG_Config();
IT_Config(); //中断相关配置
}
static void IWDG_Config(void)
{
IWDG_KR = 0x55; //关写保护
IWDG_PR = 0x00; //预分频系数4 0-6对应 4 8 16 32 64 128 256 分频
IWDG_RLR = 0xFF; //最长超时15.90 ms
IWDG_KR = 0xAA; //恢复写保护,同时相关于清狗指令->用IWDG_RLR的数值刷新计数器的内容,避免了产生看门狗的复位
//其实以上看门狗配置均为上电复位值
IWDG_KR = 0xCC; //启动独立看门狗
IWDG_KR = 0xAA; //清狗
}
static void WWDG_Config(void)
{
WWDG_WR = 0x7f;
WWDG_CR = (uint8_t)(0x80 | WWDG_COUNTER_INIT);
WWDG_WR = (uint8_t)((uint8_t)(~0x80) & (uint8_t)(0x40 | WWDG_WINDOW_VALUE));
}
static void GPIO_Config(void)
{
PA_ODR = b00000000; //初始化输出低电平
PA_DDR = b11111111; // 1=output
PA_CR1 = b11111111; //1=上拉输入或推挽输出 0=浮空输入或开漏输出 ADC时应选浮空输入,无中断
PA_CR2 = b00000000; //1=使能外部中断或10M输出 0=禁止外部中断或2M输出 中断边沿在EXTI_CRX中设置
PB_ODR = b00000000; //初始化输出低电平
PB_DDR = b11111111; // 1=output PB4 INPUT
PB_CR1 = b11111111; //1=上拉输入或推挽输出 0=浮空输入或开漏输出 ADC时应选浮空输入,无中断
PB_CR2 = b00000000; //1=使能外部中断或10M输出 0=禁止外部中断或2M输出 中断边沿在EXTI_CRX中设置
PC_ODR = b00000000; //初始化输出电平
PC_DDR = b11111111; // 1=output PC4 INPUT
PC_CR1 = b11111111; //1=上拉输入或推挽输出 0=浮空输入或开漏输出 ADC时应选浮空输入,无中断
PC_CR2 = b00000000; //1=使能外部中断或10M输出 0=禁止外部中断或2M输出 中断边沿在EXTI_CRX中设置
// 如果硬件上没有连接RST脚,则SWIM引脚(PD1)不能配置为输出口,否则不能连上ST-LINK
PD_ODR = b00100000; //初始化输出低电平 PD5=TX初始化输出高电平,PD6=RX配置为输入
PD_DDR = b10100011; // 1=output 0=input PD2=AIN3 PD3=AIN4
PD_CR1 = b11111111; //1=上拉输入或推挽输出 0=浮空输入或开漏输出 ADC时应选浮空输入,无中断
PD_CR2 = b00010000; //1=使能外部中断或10M输出 0=禁止外部中断或2M输出 中断边沿在EXTI_CRX中设置
//PD4作为下降沿中断测试输入引脚,配置为上拉输入
PE_ODR = b00000000; //初始化输出低电平
PE_DDR = b11111111; // 1=output
PE_CR1 = b11111111; //1=上拉输入或推挽输出 0=浮空输入或开漏输出 ADC时应选浮空输入,无中断
PE_CR2 = b00000000; //1=使能外部中断或10M输出 0=禁止外部中断或2M输出 中断边沿在EXTI_CRX中设置
}
static void TIM1_PWM_Config(void)
{
//须要在选项字节中配置使能对应的PWM功能管脚,同时开启对应的时钟
TIM1_PSCRH = 0x00; //预分频器 16bit fCK_CNT = fCK_PSC / (PSCR[15:0] + 1)
TIM1_PSCRL = 0x00;
TIM1_ARRH = (uint8_t)((800 - 1) >> 8); //自动重载值 16bit 即周期寄存器 16M/800=20K
TIM1_ARRL = (uint8_t)((800 - 1));
//TIM1_CR1
//TIM1_CR1_bit.CEN = 1; //CEN:允许计数,最后再开启
TIM1_CR1_bit.UDIS = 0; //UDIS:禁止更新
TIM1_CR1_bit.URS = 0; //URS:更新请求源
TIM1_CR1_bit.OPM = 0; //0:在发生更新事件时,计数器不停止;
TIM1_CR1_bit.DIR = 0; //0:计数器向上计数;
TIM1_CR1_bit.CMS = 0; //00:边沿对齐模式。计数器依据方向位(DIR)向上或向下计数。
TIM1_CR1_bit.ARPE = 1; //1:TIM1_ARR寄存器由预装载缓冲器缓冲。
TIM1_EGR_bit.UG = 1; //产生一次更新事件,更新分频系数与TIMx_CNTR
TIM1_RCR = 0x00; //重复计数寄存器,即Reload事件发生了多少次:TIM1_RCR+1
//这意味着在PWM模式中,(TIM1_RCR+1)对应着:
//- 在边沿对齐模式下,PWM周期的数目;
//- 在中心对称模式下,PWM半周期的数目;
// 通道1;
TIM1_CCMR1_bit.CC1S = 0; //CC1S[1:0]:捕获/比较1 选择
TIM1_CCMR1_bit.OC1FE = 0; //OC1FE:输出比较1 快速使能
TIM1_CCMR1_bit.OC1PE = 1; //OC1PE:输出比较1预装载使能
TIM1_CCMR1_bit.OC1M = 7; //110:PWM模式1,111:模式2
TIM1_CCMR1_bit.OC1CE = 0; //0:OC1REF 不受ETRF输入(来自TIM1_TRIG引脚)的影响; 1:一旦检测到ETRF输入高电平,OC1REF=0。
TIM1_CCER1_bit.CC1E = 1; //1=输出使能
TIM1_CCER1_bit.CC1P = 0; //0=高电平有效 P
TIM1_CCER1_bit.CC1NE = 1; //1=输出使能 --
TIM1_CCER1_bit.CC1NP = 0; //0=高电平有效--互补输出 N
TIM1_CCR1H = 0x00;
TIM1_CCR1L = 0x00; //占空比寄存器,CH1
// 通道2;
TIM1_CCMR2_bit.CC2S = 0; //CC1S[1:0]:捕获/比较1 选择
TIM1_CCMR2_bit.OC2FE = 0; //OC1FE:输出比较1 快速使能
TIM1_CCMR2_bit.OC2PE = 1; //OC1PE:输出比较1预装载使能
TIM1_CCMR2_bit.OC2M = 7; //110:PWM模式1,111:模式2
TIM1_CCMR2_bit.OC2CE = 0; //0:OC1REF 不受ETRF输入(来自TIM1_TRIG引脚)的影响; 1:一旦检测到ETRF输入高电平,OC1REF=0。
TIM1_CCER1_bit.CC2E = 1; //1=输出使能
TIM1_CCER1_bit.CC2P = 0; //0=高电平有效 P
TIM1_CCER1_bit.CC2NE = 1; //1=输出使能 -- //
TIM1_CCER1_bit.CC2NP = 0; //0=高电平有效--互补输出 N
TIM1_CCR2H = 0x00;
TIM1_CCR2L = 0x00; //占空比寄存器,CH2
// TIM1_CR2 = ;
// TIM1_SMCR = ; 从模式控制寄存器
// TIM1_ETR = ; 外部触发寄存器
//TIM1_IER 中断使能寄存器
TIM1_IER_bit.UIE = 1; //更新中断
TIM1_IER_bit.CC1IE = 0; //捕获/比较1中断
TIM1_IER_bit.CC2IE = 0; //捕获/比较2中断
TIM1_IER_bit.CC3IE = 0; //捕获/比较3中断
TIM1_IER_bit.CC4IE = 0; //捕获/比较4中断
TIM1_IER_bit.COMIE = 0; //COM中断
TIM1_IER_bit.TIE = 0; //触发中断
TIM1_IER_bit.BIE = 0; //刹车中断
// TIM1_SR1 = ; 状态寄存器 1
// TIM1_SR2 = ; 状态寄存器 2
// TIM1_EGR = ; 事件产生寄存器
//刹车寄存器
TIM1_BKR_bit.MOE = 1; //1:如果设置了相应的使能位(TIM1_CCERX寄存器的CCIE位),则使能OC和OCN输出
TIM1_CR1_bit.CEN = 1; //CEN:允许计数
}
/**
* @brief Configure TIM2 to generate an update interrupt each 0.5ms
* @param None
* @retval None
*/
void TIM4_Config(void)
{
//IM4_PSCR_bit.PSC = 7; //分频值: 2^PSC[2:0] 定时器时钟源为内部时钟(fMASTER)。 (1/16M)*128=8us
//IM4_ARR = 124; //自动重载值 (124+1)*8us=1ms
TIM4_PSCR_bit.PSC = 4; //分频值: 2^PSC[2:0] 1/16M)*2^4=1us
TIM4_ARR = 99; //自动重载值 (99+1)us
TIM4_EGR_bit.UG = 1; //产生一次更新事件,更新分频系数与TIM4_CNTR
TIM4_CR1_bit.ARPE = 1; //1:TIM4_ARR寄存器通过缓冲预装载
TIM4_SR_bit.UIF = 0; //TIM4 溢出中断标志
TIM4_IER_bit.UIE = 1; //使能TIM4 溢出中断
TIM4_CR1_bit.CEN = 1; //使能TIM4
}
/**
* @brief UART1 Configuration for interrupt communication
* @param None
* @retval None
*/
//
static void UART1_Config(void)
{
WORD_UNION UART1_BRR;
UART1_CR1_bit.PIEN = 0; //校验中断使能 0:中断被禁止 1:当USART_SR中的PE为1时,产生USART中断
UART1_CR1_bit.PS = 0; //0:偶校验。 1:奇校验
UART1_CR1_bit.PCEN = 0; //1:奇偶校验控制被使能
UART1_CR1_bit.WAKE = 0; //唤醒方法
UART1_CR1_bit.M = 0; //8bit数据格式
UART1_CR1_bit.UART0 = 0; //0:UART使能 1:UART预分频器和输出禁用
UART1_CR1_bit.T8 = 0; //9bit数据格式 下的发送数据位8
UART1_CR1_bit.R8 = 0; //9bit数据格式 下的接收数据位8
UART1_CR3_bit.STOP = 0; //00:1个停止位;01:保留 10:2个停止位;11:1.5个停止位;
UART1_BRR.all = 1666; //16M/1666=9603
//UART1_BRR2=UART_DIV[15:12]高4位 UART_DIV[3:0]低4位
UART1_BRR2 = UART1_BRR.byte.H & 0xf0;
UART1_BRR2 |= UART1_BRR.byte.L & 0x0f;
//UART1_BRR1=UART_DIV[11:4]
UART1_BRR1 = (uint8_t)(UART1_BRR.all>>4); //中间8位
//UART1_CR2_bit.SBK = 1; //SBK: 发送断开帧
//UART1_CR2_bit.RWU = 1; //RWU: 接收唤醒
UART1_CR2_bit.REN = 1; //接收使能
UART1_CR2_bit.TEN = 1; //发送使能
//UART1_CR2_bit.ILIEN= 1; //ILIEN: IDLE中断使能
UART1_CR2_bit.RIEN = 1; //接收中断使能 1:当USART_SR中的OR或者RXNE为1时,产生USART中断。
//UART1_CR2_bit.TCIEN= 1; //发送完成中断使能 1:当USART_SR中的TC为1时,产生USART中断。要发送时再使能中断(会立即产生中断)
//UART1_CR2_bit.TIEN = 1; //发送中断使能 1:当USART_SR中的TXE为1时,产生USART中断。
//UART1_SR_bit.TC &= 0; //读该位来清零
//UART1_DR = 0xaa; //写入要发送的数据
}
/**
* @brief Configure ADC
*
* @param None
* @retval None
*/
static void ADC_Config(void)
{
// 当作为模拟输入时可以关闭输入施密特触发器来降低功耗
ADC_TDRH = b00000000; //1=ADC输入禁止施密特触发 ***********ADC时应选浮空输入,无中断
ADC_TDRL = b00011000; //共16通道 AIN3-AIN4
ADC_CR1_bit.ADON = 0; //ADON: A/D 转换开/关
ADC_CR1_bit.CONT = 0; // 0:单次转换模式 1:连续转换模式
ADC_CR1_bit.SPSEL = 0; // 预分频选择位 000->111对应 2 3 4 6 8 10 12 18分频
//ADC_CR2_bit.SCAN = 1; //1:使能扫描模式 0:不使能扫描模式
ADC_CR2_bit.ALIGN = 1; //1:数据右对齐。(低8字节在ADC_DRL寄存器,其余高字节位在ADC_DRH寄存器)读顺序
//应先读低位,再读高位字节或整个一起读
ADC_CR2_bit.EXTSEL = 0; //外部事件触发和启动ADC 00:内部定时器1 TRG事件 01:ADC_ETR 引脚上的外部中断 其它值保留
ADC_CR2_bit.EXTTRIG = 0; //EXTTRIG: 外触发使能位
//ADC_CR3_bit.OVR = 0; //1:数据缓存发生了数据溢出事件
ADC_CR3_bit.DBUF = 0; //1:数据缓存功能使能,扫描模式时使用.
ADC_CSR_bit.CH = 4; // CH[3:0] : 选择转换通道 或指定从AN0到ANx扫描转换
//ADC_CSR_bit.AWDIE = 0; //1: 使能AWD模拟看门狗中断
//ADC_CSR_bit.EOCIE = 1; //1:使能转换结束中断
//ADC_CSR_bit.AWD = 0; //AWD: 模拟看门狗标志
ADC_CSR_bit.EOC = 0; //EOC: 转换结束
ADC_CR1_bit.ADON = 1; //第一次置1将把ADC从低功耗模式下唤醒,之后才是启动ADC
//ADC_DBxRH 缓冲寄存器
//ADC_DBxRL
//ADC_DRL 数据寄存器
//ADC_DRH
}
void IT_Config(void)
{
// 中断配置------------------------------------------
//ITC_SPR3_bit.VECT11SPR = 0;//Timer1最低优先级,
//ITC_SPR4_bit.VECT15SPR = 0;//Timer3最低优先级,
//ITC_SPR6_bit.VECT21SPR = 0; //UART1/3接收满 最低优先级
//ITC_SPR6_bit.VECT22SPR = 2; //adc中断为最高优先级
//ITC_SPR6_bit.VECT23SPR = 0; //Timer4最低优先级,2为最高,3为禁止优先级(复位默认值)
//EXTI_CR1:外部中断控制寄存器1 设置何种边沿触发
EXTI_CR1_bit.PAIS = 0;//[1:0] 00:下降沿和低电平触发
EXTI_CR1_bit.PBIS = 0;//[3:2] 01:仅上升沿触发
EXTI_CR1_bit.PCIS = 0;//[5:4] 10:仅下降沿触发
EXTI_CR1_bit.PDIS = 2;//[7:6] 11:上升沿和下降沿触发
//EXTI_CR2;
EXTI_CR2_bit.PEIS = 0;//[1:0] GPIOE,配置同EXTI_CR1
EXTI_CR2_bit.TLIS = 0;//[2] TLI 0:下降沿触发 , 1:上升沿触发
}