×
嵌入式 > 技术百科 > 详情

STM8S各个模块初始化

发布时间:2020-06-20 发布时间:
|
/***************可选择的内部或者外部时钟*******************/

#ifdef  HSE_EXT
void ClkInit(void)
{
 CLK_ICKR = 0X00;      //禁止高速内部时钟,从停机(Halt) 或活跃停机(Active Halt) 模式快速唤醒禁止
 CLK_ECKR |= 0X01;      //使能外部时钟
 while(!(CLK_ECKR & 0x02));
                //看外部晶振是否启动
 CLK_ECKR |= 0X01;      //使能外部时钟
 CLK_CKDIVR = 0Xf9;    //外部12M HZ晶振作为CPU时钟 
                       //入选24Mhz就在CLK_SWCR |= 0X02;出现问题
 CLK_SWR = 0XB4;       //主时钟选择为外部晶振
 while(!(CLK_SWCR & 0x8));
 CLK_SWCR |= 0X02;      //时钟切换
 CLK_PCKENR1 = 0Xaf;   //使能fMASTER时钟与对应外设的连接(仅I2C和TIM2,and TIM1)还有UART1,uart3 spi
 CLK_PCKENR2 = 0X00;    //0X0C;
 CLK_CSSR = 0X00;      //时钟安全系统寄存器关
 while((CLK_CCOR & 0x04));  //空闲才可以写CCOSEL
 CLK_CCOR |= 0X0d;          //使能CCO始终输出,6M
 while(!(CLK_CCOR & 0x04)); //看CCO输出的时钟是否正在工作
 while((CLK_CCOR & 0x02));  //等待可输出时钟可用
 //CLK_HSITRIMR = 0X00-1; //HSI时钟修正寄存器,HSITRIM[3:0]:HSI修正值
}
#else
void ClkInit(void)
{
 CLK_ICKR=0X01;      //时能高速内部时钟,从停机(Halt) 或活跃停机(Active Halt) 模式快速唤醒使能
 CLK_ECKR=0X00;      //禁止外部时钟
 CLK_SWR =0XE1;      //选择16M内部时钟为主时钟
 CLK_SWCR=0X00;      //禁止时钟切换
 CLK_CKDIVR=0X08;    //8MHZ   [4:3]01:fHSI = fHSI RC输出/2 ,  [2:0]000:fCPU = fMASTER 
 CLK_PCKENR1 = 0Xaf;   //使能fMASTER时钟与对应外设的连接(仅I2C和TIM2,and TIM1)还有UART1,uart3 spi
 CLK_PCKENR2 = 0X00;    //0X0C;
 CLK_CSSR=0X00;      //时钟安全系统寄存器关
 CLK_HSITRIMR=0X00-1;   //HSI时钟修正寄存器,HSITRIM[3:0]:HSI修正值
}
#endif

/********外部中断****************/
void InterruptInit(void)
{
  PD_DDR &=~(0X40);           //PD6设置为按键输?
  PD_CR1 |=0X40;
  PD_CR2 &=~(0X40);             //禁止外部中断
//  PD_CR2 |=0X40;           //使能外部中断
 EXTI_CR1 |=0X80;    //PD6下降沿出触发中断
//  EXTI_CR1 |=0X40;    //PD6上升沿出触发中断
}

/*****************串口收发******************/
void Uart3Init(void)
{
        UART3_CR1 = 0x00;
        UART3_CR2 = 0x00;
        UART3_CR3 = 0x00;       //1个停止位
        
        UART3_BRR2 = 0x04;     //24M的Fmaster下9600的波特率
    UART3_BRR1 = 0x9c;   //24000000/9600 = 0x09c4
        UART3_CR2 = 0x2c;      //发送接收都使能,使能接收中断  
}

void Uart3SendChar(U8 *Send_Buff,U8 Cnt)
{
     U8 i;
     for(i=0;i    {
        while(!(UART3_SR & 0x80));
        UART3_DR=Send_Buff[i];
   }
}

/***********定时器**************************/
void Timer1Init(void)
{
  TIM1_CR1 |=0X04;      //自动重载,只有溢出才产生更新中断
  TIM1_IER |=0X01;     //允许更新中断
//  TIM2_SR1=0X00;    //状态寄存器
  TIM1_PSCR =0X01;     //PSC[3:0]:预分频器的值 ,开预分频功能不许使能EGR中的UG位
// TIM1_PSCR =0X00;     //PSC[3:0]:4预分频器的值 
  TIM2_EGR |=0X01;     //时间产生状态寄存器,重新初始化计数器,并产生一个更新事件。
 //如果不开预分频功能,此位可以删去

//TIM2_CCMR1=0X00;   //捕获/比较模式寄存器,可用于选择PWM输出端口 
//TIM2_CCMR1=0X68;      //PWM模式,通道1,预装载使能
 
// TIM2_CCMR2=0X68;       //PWM模式,通道2,预装载使能
// TIM2_CCER2=0X03;       //使能PWM输出通道
 
// TIM2_CCER1=0X03;       //使能PWM输出通道
  TIM1_CNTRH=0X9C;      //计数值
  TIM1_CNTRL=0X40; 
  TIM1_ARRH=0X9C;       //自动重载值(10ms进一次中断),8M2分频,40000/4000000=10ms
  TIM1_ARRL=0X40;  
  TIM1_CR1 |=0X01;       //开计数器
}

/************AWU唤醒********************/
void AWU_Open(void)
{
 AWU_APR = 0X3E;    //APPRdiV=64
 AWU_TBR = 0X0D;    //time interval = 2^11 *APPRdiV/Fls=2048*64/128KHZ=1S    0D=2S
//  AWU_TBR = 0X0E;    //time interval = 2^11 *APPRdiV/Fls=2048*64/128KHZ=1S  0E==大约5S
 AWU_CSR = 0x30;   //enable AWU,AWU_INT
  CLK_ICKR |= 0X20;  //1:活跃停机(Active Halt)  模式下主dian ya tiao jie qi guan bi
}

void AWU_Close(void)
{
 AWU_APR = 0X3F;    //APPRdiV
 AWU_TBR = 0X00;    //disable time interval 
 AWU_CSR = 0x00;   //disable AWU
 CLK_ICKR &= ~(0X20);
}

void EEPROM_Init(void)
{
    FLASH_CR1 = 0x00;
    FLASH_CR2 = 0x00;
    FLASH_DUKR = MASS_KEY1;
    FLASH_DUKR = MASS_KEY2;                         //密钥使能
    while(!(FLASH_IAPSR&0x08));        /*等待写保护解锁*/
}

/***********EEPROM***************************/
u8 EEPROM_Write(u8 addr,u8 dat)
{
     u16 TimeOut; 
    *((u8*)(addr + EEP_BASE)) = dat;

    for( TimeOut = 0; TimeOut < 0xFFFF; TimeOut++ ) 
    { 
         if( FLASH_IAPSR & ( WR_PG_DIS | EOP_BIT ))return 1;     //编程完成或者写到了写保护区
    } 
    return 0;
    //超时退出    
   // while(!(FLASH_IAPSR&0x02));        /*等待写完成*/
}

u8 EEPROM_Read(u8 addr)             
{
    return  *((u8*)(EEP_BASE + addr));
}

void EEPROM_THREE_BYTE_WRITE(void)
{

 EEPROM_Write(0x00,i2c_buff[0]);
 EEPROM_Write(0x01,i2c_buff[1]);
 EEPROM_Write(0x02,i2c_buff[2]);
}

void EEPROM_THREE_BYTE_READ(void)
{
 if(ADC_OnOff==1)
   ADC_ON_OR_OFF=2;      
 else
   ADC_ON_OR_OFF=EEPROM_Read(0x00);
 ADC_OPEN_MIN=EEPROM_Read(0x01);
 ADC_OPEN_TIME=EEPROM_Read(0x02);
}

/**************ADC***********************/
void adc_init(void)
{
  ADC_CR1 |=0X00;     //关闭ADC,2分频 
  ADC_CR2 |=0X08;      //数据右对齐,low 8BIT   AT   ADC_DRL;非扫描模式
 ADC_CSR =0X04;     //选择通道4, 禁止中断 
}

/********取走ADC转换yi个通道的数据**********/
u16 adc_converter(void)

  u8  m;
  
  for(m=0;m<30;m++);       //等待上电完成
  ADC_CR1 |=0X1;           //启动转换 
  while(!(ADC_CSR&0x80));  //等待转换结束   14个时钟周期 
  ADC_CSR &= 0X7F;         //清除中断标志 
  
  return ADC_DR;  
}

/****************I2C**************************/
void I2C_init(void) 

I2C_CCRH   = 0x00;    //标准I2C接口 
//I2C_CCRL    = 80 ; 
//I2C_FREQR  = 0x10;     //输入外设时钟频率为2MHz 
I2C_CR1    = 0x00;      //禁止I2C外设 
I2C_FREQR  = 8;      // 8MHZ  //经测试主芯片时钟至少》8Mhz才能正常收到数据
I2C_OARL   = SLAVE_ADDRESS;       // 
I2C_OARH   = 0x40; // 七位
//I2C_OARH   = 0xC0 | ((SLAVE_ADDRESS & 0x300) >> 7); // 十位

I2C_CR1    = 0x01;      //开I2C
I2C_CR2   |= 0x04;      //只产生应答信号,不产生起始和停止位
I2C_ITR    = 0x07;     //使能中断
}


void spi_init(void)
{
 SPI_CR2 = 0X01;
  SPI_CR1 = 0X44;  //8MHZ  主模式
  
  PB_DDR |= 1 << 5;                //SCK
  PB_CR1 |= 1 << 5;                //output
  
  PB_DDR |= 1 << 6;                //MOSI
  PB_CR1 |= 1 << 6;                //output

  PB_DDR &= ~(1 << 7);        //MISO
  PB_CR1 |= 1 << 7;                //in put with pull-up
        
  CLK_PCKENR1 |= 0x10;
  SPI1_CR1  = 0x04;        
  SPI1_CR2 = 0x03; 
  SPI1_CRCPR = 0x07; 
  SPI1_ICR   = 0x00; 
  SPI1_CR1 |= 0x40;
}

/*************SPI**************************/
UINT8 SPI_RW(UINT8 byte)
{
        unsigned char data;
        //while(SPI1_SR&0x80); //Busy flag
        while(!SPI1_SR&0x02);
        SPI1_DR = byte;
        while(!SPI1_SR&0x01); 
        _asm("nop");
        _asm("nop");
        _asm("nop");
        _asm("nop");
        data = SPI1_DR; 
        return(data);
}


/****************按键*************************/
extern u16 keyvalue;
u8  f_keytime;
//extern u8  KeyRestFlag;
u16 u16Timer1Cnt;
void keyscan(void)
{
 static u16 f_key_state=0;
  u8 key_up_flag=0;
 static u16 keyoldbuf=0;
 static u16 keyinbuf=0,keychkbuf=0,keycvtbuf=0;
 if(f_keytime==1)
  {
   f_keytime=0;
   key_up_flag=PC_IDR&0x10;
    if(key_up_flag==0x00)  //
     {
       if(u16Timer1Cnt>=KeyInContinue1S)
     {
//       KeyRestFlag=0;
           u16Timer1Cnt=0;
        keyinbuf=KeyRst;
     }
     }
    else
     { 
//       KeyRestFlag=0;
       keyinbuf=0;
       u16Timer1Cnt=0;
     }
   if(keyinbuf==keychkbuf)
    {
     if(f_key_state)
      {
       keycvtbuf=keychkbuf;
       f_key_state=0;
      }
    }
   else
    {
     keychkbuf=keyinbuf;
     f_key_state=1;
    }
  }
 if(keycvtbuf!=keyoldbuf)
  {
   keyvalue=keycvtbuf&(~keyoldbuf);
   keyoldbuf=keycvtbuf;
  }
/*****    
 if(keycvtbuf!=keyoldbuf)     //按键按下
  {
//   keyvalue|=keycvtbuf&(~keyoldbuf);
            keymediavalue=keycvtbuf&(~keyoldbuf);
//   keyoldbuf=keycvtbuf;
   key_up_flag=1;
//   return  keyvalue;
  }
  if(key_up_flag==1)       //按键抬起
    if(keycvtbuf==keyoldbuf)
      {
     key_up_flag=0;
     keyvalue=keymediavalue;
   }
  }
//  return 0;
****/


『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
激光跟踪仪市场2023年有望达5.216亿美元