STM8S003使用总结

目录

一、系统时钟

1.初始化

 2.HSE需要修改的地方

二、定时器

1.TIM1

2.中断回调函数

3.TIM2 

4.Delay

三、串口

1.标准库

2.寄存器库 

3.中断回调函数

4.printf

 5.普通发送函数

四、GPIO

1.初始化

标准库

寄存器库

2. 中断

标准库

寄存器库

 中断回调函数

五、I2C

1.标准库

2.寄存器库

3.中断回调函数

六、EEPROM

1.寄存器库

2.写函数

七、IWDG

寄存器库


一、系统时钟

1.初始化

ErrorStatus clk_return_status;
CLK_Source_TypeDef clk_source;
u32 u32_clk_freq;
void CLK_Config(void)
{
  CLK_LSICmd(ENABLE);                                       // 使能或禁用低速内部(LSI)时钟

#ifdef HSE
  CLK_HSECmd(ENABLE);                                       // 使能或禁用高速外部(HSE)时钟
  while (SET != CLK_GetFlagStatus(CLK_FLAG_HSERDY));        // 等待HSE
  clk_return_status = CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSE, DISABLE, CLK_CURRENTCLOCKSTATE_DISABLE);
#else
  CLK_HSICmd(ENABLE);                                       // 使能或禁用高速内部(HSI)时钟
  CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);            // 配置高速内部时钟(HSI)的预分频器
  while (SET != CLK_GetFlagStatus(CLK_FLAG_HSIRDY));        // 等待HSI
#endif

clk_source = CLK_GetSYSCLKSource();
u32_clk_freq = CLK_GetClockFreq();
// printf("%u",u32_clk_freq);
  CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV1);                  // 配置系统时钟(SYSCLK)的预分频器
}

 2.HSE需要修改的地方

 使用外部高速晶振时默认为无源晶振,有源晶振需要修改Option Bytes中的EXTCLK为1

 修改外部高速晶振的频率,默认为16MHz,CLK_GetClockFreq();函数中需要用到

测试时外部晶振使用时还存在问题

二、定时器

1.TIM1

#define flicker_frequency 200                       // ms

void TIM1_Config(void)
{
  TIM1_TimeBaseInit(((CLK_GetClockFreq()/1000)-1), TIM1_COUNTERMODE_UP, flicker_frequency+1, 0);// 16M/(16M/1000-1+1)/200=200ms
  TIM1_ClearFlag(TIM1_FLAG_UPDATE);                         // 清楚更新标志位
  TIM1_ITConfig(TIM1_IT_UPDATE, ENABLE);                    // 使能更新中断
  enableInterrupts();                                       // 开启中断
}

2.中断回调函数

/*main.h*/
typedef union
{
    uint8_t all;
    struct
    {
        uint8_t relay:2;
        uint8_t led_R:2;
        uint8_t led_G:2;
        uint8_t led_Y:2;
    }bits;

} slave_status_u;

/*stm8s_it.c*/
INTERRUPT_HANDLER(TIM1_UPD_OVF_TRG_BRK_IRQHandler, 11)
{
  if (TIM1_GetITStatus(TIM1_IT_UPDATE) != RESET)  
  {  
    TIM1_ClearITPendingBit(TIM1_IT_UPDATE);             // 清除中断标志  
    // printf("Timer 1 interrupt triggered\r\n");

    if(status.bits.led_R == 3)
    {
      GPIO_WriteReverse(LED_GPIO_PORT,LED_GPIO_R);
    }
      
    if(status.bits.led_G == 3)
    {
      GPIO_WriteReverse(LED_GPIO_PORT,LED_GPIO_G);
    }
      
    if(status.bits.led_Y == 3)
    {
      GPIO_WriteReverse(LED_GPIO_PORT,LED_GPIO_Y); 
    }
  }
}

3.TIM2 


void TIM2_Config(void)
{
  // CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER2, ENABLE); //使能或禁用特定外设的时钟
  TIM2_TimeBaseInit(TIM2_PRESCALER_1, (CLK_GetClockFreq()/1000)-1);              // 1ms
  TIM2_ClearFlag(TIM2_FLAG_UPDATE);                         // 清楚更新标志位
  // TIM2_ITConfig(TIM2_IT_UPDATE, ENABLE);                    // 使能更新中断
  enableInterrupts();                                       // 开启中断
}

4.Delay


void Delay (uint16_t Times)
{
  TIM2_Cmd(ENABLE);
  while(Times--)
  {
    while(RESET == TIM2_GetFlagStatus(TIM2_FLAG_UPDATE));
    TIM2_ClearFlag(TIM2_FLAG_UPDATE);
  }
  TIM2_Cmd(DISABLE);
}

三、串口

1.标准库


void UART_Config(void)
{
  /* Deinitializes the UART1 peripheral */
    UART1_DeInit();
    /* UART1 configuration -------------------------------------------------*/
    /* UART1 configured as follow:
          - BaudRate = 9600 baud            波特率
          - Word Length = 8 Bits            数据位长度:8位
          - One Stop Bit                    停止位:1位
          - No parity                       奇偶校验:无奇偶校验
          - Receive and transmit enabled    同步时钟:禁用
          - UART1 Clock disabled            通信模式:收发模式
     */
    /* Configure the UART1 */
    UART1_Init((uint32_t)Baudrate, UART1_WORDLENGTH_8D, UART1_STOPBITS_1, UART1_PARITY_NO,
                UART1_SYNCMODE_CLOCK_DISABLE, UART1_MODE_TXRX_ENABLE);
    
    /* Enable UART1 IDLE interrupt*/
    UART1_ITConfig(UART1_IT_RXNE_OR, ENABLE);//开启接收中断
    UART1_ITConfig(UART1_IT_IDLE, ENABLE);//开启空闲中断
    /* Enable general interrupts */
    enableInterrupts();    
}

2.寄存器库 


void LL_UART_Config(void)
{
    UART1->CR1=0x00;
    UART1->CR2=0x00;
    UART1->CR3=0x00;
    UART1->BRR2 = 0x0B;//0x05;//0x0B;     //8M、16MHz下115200波特率
    UART1->BRR1 = 0x08;//0x04;//0x08;     //8M、16MHz下115200波特率
    UART1->CR2 |= (uint8_t)UART1_CR2_TEN;//允许发送
    UART1->CR2 |= (uint8_t)UART1_CR2_REN;//允许接收
    
    /* Enable UART1 IDLE interrupt*/
    UART1->CR2 |= UART1_CR2_RIEN;
    UART1->CR2 |= UART1_CR2_ILIEN;
    /* Enable general interrupts */
    enableInterrupts();    
}

3.中断回调函数

INTERRUPT_HANDLER(UART1_RX_IRQHandler, 18)
 {
  if(UART1->SR & UART1_SR_RXNE)
  {
    if(UART1data.rxnum < 40)
      UART1data.Data[UART1data.rxnum++] = UART1->DR;
    else
      UART1data.flag = 1;
  }
    
  else if(UART1->SR & UART1_SR_IDLE)
  {
    //清除空闲中断
    UART1->SR;
    UART1->DR;
    UART1data.flag = 1;
  }
 }

4.printf

//printf 
/**
  * @brief Retargets the C library printf function to the UART.
  * @param c Character to send
  * @retval char Character sent
  */
PUTCHAR_PROTOTYPE
{
  /* Write a character to the UART1 */
  UART1_SendData8(c);
  /* Loop until the end of transmission */
  while (UART1_GetFlagStatus(UART1_FLAG_TXE) == RESET);

  return (c);
}

/**
  * @brief Retargets the C library scanf function to the USART.
  * @param None
  * @retval char Character to Read
  */
GETCHAR_PROTOTYPE
{
#ifdef _COSMIC_
  char c = 0;
#else
  int c = 0;
#endif
  /* Loop until the Read data register flag is SET */
  while (UART1_GetFlagStatus(UART1_FLAG_RXNE) == RESET);
    c = UART1_ReceiveData8();
  return (c);
}

 5.普通发送函数

void UART1_SendString(const char *str)
{
  // 遍历字符串,直到遇到空字符 '\0'(字符串结束标志)
  while (*str != '\0') 
  {
    UART1_SendData8((uint8_t)*str);
    while(!UART1_GetFlagStatus(UART1_FLAG_TC));
    str++;
  }
}

四、GPIO

1.初始化

标准库


void GPIO_Config(void)
{
  // GPIO_Init(GPIOB, GPIO_PIN_5, GPIO_MODE_OUT_PP_LOW_FAST);          // 板载灯,与IIC冲突
  // GPIO_Init(ARM_IO1_PORT, ARM_IO1_PINS, GPIO_MODE_IN_FL_NO_IT);     // 暂未使用
  // GPIO_Init(ARM_IO2_PORT, ARM_IO2_PINS, GPIO_MODE_IN_FL_NO_IT);     // 暂未使用
  // GPIO_Init(GPIOA, GPIO_PIN_2, GPIO_MODE_OUT_PP_LOW_FAST);          // 空闲引脚

  GPIO_Init(LED_GPIO_PORT, (GPIO_Pin_TypeDef)LED_GPIO_PINS, GPIO_MODE_OUT_PP_HIGH_FAST);
  GPIO_Init(RELAY_GPIO_PORT, (GPIO_Pin_TypeDef)RELAY_GPIO_PINS, GPIO_MODE_OUT_PP_LOW_FAST);
  GPIO_Init(REL_GPIO_PORT, REL_GPIO_2, GPIO_MODE_IN_PU_NO_IT);
}

寄存器库

void LL_GPIO_Config(void)
{
    GPIOC->DDR = 1<<4|1<<5|1<<6|0<<7;
    GPIOC->CR1 = 1<<4|1<<5|1<<6|1<<7;
    GPIOC->CR2 = 1<<4|1<<5|1<<6|0<<7;
    GPIOC->ODR = 0<<4|0<<5|0<<6|0<<7;

    GPIOD->DDR = 1<<2|1<<3|1<<4;
    GPIOD->CR1 = 1<<2|1<<3|1<<4;
    GPIOD->CR2 = 1<<2|1<<3|1<<4;
    GPIOD->ODR = 1<<2|1<<3|1<<4;
}

2. 中断

标准库

  GPIO_Init(ARM_IO1_PORT, ARM_IO1_PINS, GPIO_MODE_IN_FL_IT);
  EXTI_SetExtIntSensitivity(EXTI_PORT_GPIOA,EXTI_SENSITIVITY_RISE_FALL);
  enableInterrupts();

寄存器库

    GPIOA->DDR = 0<<3;
    GPIOA->CR1 = 0<<3;
    GPIOA->CR2 = 1<<3;
    GPIOA->ODR = 0<<3;

    EXTI->CR1 &= (uint8_t)(~EXTI_CR1_PAIS);
    EXTI->CR1 |= (uint8_t)(EXTI_SENSITIVITY_RISE_FALL);

 中断回调函数

INTERRUPT_HANDLER(EXTI_PORTA_IRQHandler, 3)
{
  printf("EXTI");
  if ((GPIO_ReadInputData(ARM_IO1_PORT) & ARM_IO1_PINS) == ARM_IO1_PINS)
  {
    GPIO_WriteHigh(ARM_IO2_PORT,ARM_IO2_PINS);
    printf("high\r\n");
  }

  else if ((GPIO_ReadInputData(ARM_IO1_PORT) & ARM_IO1_PINS) == 0x00)
  {
    GPIO_WriteLow(ARM_IO2_PORT,ARM_IO2_PINS);
    printf("LOW\r\n");
  }
}

五、I2C

1.标准库

void IIC_Config(void)
{
  // CLK_PeripheralClockConfig(CLK_PERIPHERAL_I2C, ENABLE); //使能或禁用特定外设的时钟
  // I2C_DeInit();
  I2C_Init(SLAVE_CLOCK, SLAVE_ADDRESS, I2C_DUTYCYCLE_2, I2C_ACK_CURR, I2C_ADDMODE_7BIT, CLK_GetClockFreq()/1000000);
  I2C_ITConfig((I2C_IT_TypeDef)(I2C_IT_ERR | I2C_IT_EVT), ENABLE);
  enableInterrupts();
  // I2C_Cmd(ENABLE);
}

2.寄存器库

void LL_IIC_Config(void)
{
  //IIC
  /* Write new frequency bits */
  I2C->FREQR = 16;
  /* Write CCR with new calculated value */
  I2C->CCRL = (uint8_t)((16*1000000)/(SLAVE_CLOCK*3));
  I2C->CCRH = (uint8_t)((uint8_t)((uint8_t)(((16*1000000)/(SLAVE_CLOCK*3)) >> 8) & I2C_CCRH_CCR) | I2C_CCRH_FS);
  /* Enable I2C */
  I2C->CR1 |= 0x01;
  /* Enable the acknowledgement */
  I2C->CR2 |= I2C_CR2_ACK;
  /* Configure (N)ACK on current byte */
  I2C->CR2 &= (uint8_t)(~I2C_CR2_POS);
  /*--------------------------- I2C OAR Configuration ------------------------*/
  I2C->OARL = (uint8_t)(SLAVE_ADDRESS);
  I2C->OARH = (uint8_t)((uint8_t)(I2C_ADDMODE_7BIT | I2C_OARH_ADDCONF) | (uint8_t)((SLAVE_ADDRESS & (uint16_t)0x0300) >> (uint8_t)7));

  // 启用IIC中断
  I2C->ITR |= (uint8_t)(I2C_IT_ERR | I2C_IT_EVT | I2C_IT_BUF);
  enableInterrupts();
}

3.中断回调函数

/*stm8s_it.h*/
typedef struct {  
    uint8_t Command;    // 命令
    uint8_t SubCmd;     // 子命令
    uint8_t SubData;    // 子命令数据
} MyBuffer;

typedef enum
{
  iic_start = 0,
  iic_sent,
  iic_received ,
  iic_addr,
  iic_stop,
  iic_sending,
  iic_af,
}iic_status_e;

extern MyBuffer protocol;

/*stm8s_it.c*/
#define Protocol_return 0x80

#define TXE_flag    (1 << 7)
#define RXNE_flag   (1 << 6)
#define ADDR_flag   (1 << 1)
#define AF_flag     (1 << 2)
#define STOPF_flag  (1 << 4)
#define TRA_mode    (1 << 2)

uint8_t Slave_Buffer_Rx[10];
uint8_t TransmitData[10];
uint8_t Tx_Idx = 0, Rx_Idx = 0;
MyBuffer protocol;
iic_status_e state = iic_start;

INTERRUPT_HANDLER(I2C_IRQHandler, 19)
{
  uint8_t temp=0;
  // printf("LastEvent=%d\r\n",I2C_GetLastEvent());
  // printf("ReceiveData=%d\r\n",I2C_ReceiveData());

  if(I2C->SR1 & TXE_flag)         // 发送完成
  {
    state = iic_sent;
  }
  else if(I2C-> SR1 & RXNE_flag)  // 接收非空
  {
    state = iic_received;
  }
  else if(I2C->SR1 & ADDR_flag)   // 地址匹配
  {
    if(I2C->SR3 & TRA_mode)       // 发送数据
    {
      state = iic_sending;
    }
    else                          // 接收数据
    {
      state = iic_addr;
      temp = I2C->SR3;
    }
  }

  else if(I2C->SR2 & AF_flag)     // 应答失败(发送完成)
  {
    I2C->SR2 &= ~AF_flag;
    state = iic_af;
  }

   if(I2C->SR1 &STOPF_flag)       // 检测到停止位
  {
    if(I2C-> SR1 & RXNE_flag)
    {
      state = iic_received;       // 接收最后一个数据时RXNE和STOPF同时出现
    }
    else
    {
      state = iic_stop;           // 接收完成
      temp = I2C->SR1;
      temp = I2C->CR2;
      I2C->CR2 = temp;
    }
  }

  switch(state)
  {
    case iic_received:
      Slave_Buffer_Rx[Rx_Idx++] = I2C_ReceiveData();
      break;
    case iic_stop:
      if(Rx_Idx != 3)
        break;

      // memcpy((uint8_t *)&protocol, Slave_Buffer_Rx, 3);
      protocol.Command = Slave_Buffer_Rx[0];
      protocol.SubCmd = Slave_Buffer_Rx[1];
      protocol.SubData = Slave_Buffer_Rx[2];
      if(DataHandle(&protocol) != HAL_OK)
      {
        protocol.SubData = 0xFF;
        #ifdef debug
          printf("IIC receive data error!\r\n");
        #endif
      }
      protocol.Command |=Protocol_return;
      Rx_Idx = 0;
      break;
    case iic_sending:
      Tx_Idx = 0;
      // memcpy(TransmitData, (uint8_t*)&protocol, 3);
      TransmitData[0] = protocol.Command;
      TransmitData[1] = protocol.SubCmd ;
      TransmitData[2] = protocol.SubData;
      I2C_SendData(TransmitData[Tx_Idx++]);
      break;
    case iic_sent:
      I2C_SendData(TransmitData[Tx_Idx++]);
      break;
    case iic_af:
      break;
  }
}

六、EEPROM

1.寄存器库

void LL_EEP_Init(void)
{
    FLASH->CR1 = 0x00;
    FLASH->CR2 = 0x00;
    FLASH->NCR2 = 0xff;
    FLASH->DUKR = MASS_KEY1;
    FLASH->DUKR = MASS_KEY2;
    while(!FLASH_IAPSR_DUL);        //等待写保护解锁
}

2.写函数

void eep_write(uint16_t addr,uint8_t dat)          //不同芯片,EEPROM容量不同-小容量640字节
{
    *((uint8_t*)(addr + EEP_BASE)) = dat;
    while(!FLASH_IAPSR_EOP);                       //等待写完成
}

七、IWDG

寄存器库

void LL_WDT_Init(void)
{
  IWDG->KR = 0xCC;       //启动看门狗
  IWDG->KR = 0x55;       //解除写保护
  IWDG->PR = 0x06;       //256分频,最高1.02秒
  IWDG->RLR = 125;       //500ms
  IWDG->KR = 0xAA;       //写保护
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值