使用STM8S自带BootLoader_2

发布者:MindfulBeing最新更新时间:2020-02-03 来源: eefocus关键字:STM8S  自带BootLoader 手机看文章 扫描二维码
随时随地手机看文章

仔细读ST支持文档 UM0560,按步骤操作。


程序准备工作: 

1.开串口接收中断,发送。


/* ********************************************

UART2  configured as follow:

  - BaudRate = 115200 baud  

  - Word Length = 8 Bits

  - One Stop Bit

  - No parity

  - Receive and transmit enabled

  -  Receive interrupt

  - UART2 Clock disabled

*********************************************/

void Uart_Init(void)

{

    UART2_DeInit();

    UART2_Init((u32)115200, UART2_WORDLENGTH_8D, UART2_STOPBITS_1,

    UART2_PARITY_NO , UART2_SYNCMODE_CLOCK_DISABLE , UART2_MODE_TXRX_ENABLE);

    UART2_ITConfig(UART2_IT_RXNE_OR,ENABLE  );

    UART2_Cmd(ENABLE );


}

void UART2_SendByte(u8 data)

{   

  /* Loop until the end of transmission */

    while ((UART2_GetFlagStatus(UART2_FLAG_TXE) == RESET)); 

    UART2_SendData8((unsigned char)data);

}


/**

  * @brief UART2 RX interrupt routine.

  * @param  None

  * @retval None

  */

#define C_UartRxMaxInx 40

uint8_t V_RxDataInx = 0;

uint8_t V_UartEndTime = 0;

uint8_t VT_RxUartData[C_UartRxMaxInx+1] = {0};

uint8_t B_RxFirts = 0;

 INTERRUPT_HANDLER(UART2_RX_IRQHandler, 21)

 {

    /* In order to detect unexpected events during development,

       it is recommended to set a breakpoint on the following instruction.

    */ 

     if(SET == UART2_GetITStatus(UART2_IT_RXNE))    //接收到数据中断

     {

        UART2_ClearITPendingBit(UART2_IT_RXNE);

        if(B_RxFirts == 0)

        {

            B_RxFirts = 1;

            V_UartEndTime =0;

            V_RxDataInx = 0;

        }   

        if(V_RxDataInx < C_UartRxMaxInx)//接收串口数据,最多接收40字节

        {

            V_UartEndTime=0;

            VT_RxUartData[V_RxDataInx] = UART2_ReceiveData8();  

            V_RxDataInx++;

        }

        else

        {

            V_UartEndTime = 0;      //超过缓存了,不在往里面写数

        }


     }

     else if(SET == UART2_GetITStatus(UART2_IT_OR)) //过载错误

     {

        UART2->SR = UART2->SR;

        UART2_ReceiveData8();       //读状态寄存器,读数据寄存器,清除中断标志

     }



 }


uint8_t B_HaveRxData = 0;

//************************************************************************

void    UartRxScan(void)

{

    if(B_RxFirts)

    {

        V_UartEndTime++;

        if(V_UartEndTime>10)//大于50ms认为是新的指令来了

        {

            B_RxFirts = 0;      //下次来数据就覆盖

            V_UartEndTime = 0;

            B_HaveRxData = 1;   //接收到真确的UART数据  

            VT_RxUartData[C_UartRxMaxInx-1]='';   //这个是保护,超过限定值就结束

        }   

    }

}


2.开定时器定时


/*

 初始化Timer2,设置1MS中断

*/

void Init_Timer2(void)

{

    TIM2_DeInit();

    TIM2_TimeBaseInit(TIM2_PRESCALER_16, 999);  //1MHz /1000 = 1000 HZ

    TIM2_ClearFlag(TIM2_FLAG_UPDATE); 

     /* Enable update interrupt */

    TIM2_ITConfig(TIM2_IT_UPDATE, ENABLE);

    TIM2_Cmd(ENABLE);

}


定时器中断服务函数,记接收超时,记反馈超时。 

接收超时单位是100ms。


 uint8_t V_SystemTimeCount = 0;

 INTERRUPT_HANDLER(TIM2_UPD_OVF_BRK_IRQHandler, 13)

 {

  /* In order to detect unexpected events during development,

     it is recommended to set a breakpoint on the following instruction.

  */

    TIM2_ClearITPendingBit(TIM2_IT_UPDATE);   //clear flag

    UartRxScan();

    V_SystemTimeCount++;

    if(V_SystemTimeCount>10)

    {

        V_SystemTimeCount=0;

        V_WaitResponceTime++;

    }

 }


/*

* 函数功能:清空接收数组

*/

void F_ClrRxUartData(void)

{

    B_RxFirts = 0;

    for(u8 i=0;i    {

        VT_RxUartData[i] = 0;

    }

}


/*

 函数功能:等待反馈

 输入参数:V_CMD_ADD  命令地址,在接收数据中的位置

           Commond    命令

           V_OverTime 最大响应时间

 输出参数:C_OverTime 超时

           C_Success  成功

           C_Waiting  等待

**/

uint8_t V_WaitResponceTime = 0;

uint8_t F_WaitResponce(uint8_t V_CMD_ADD,uint8_t Commond,uint8_t V_OverTime)

{

    if(V_WaitResponceTime >V_OverTime)

    {

        return C_OverTime;

    }

    else if(VT_RxUartData[V_CMD_ADD] == Commond) 

    {

            F_ClrRxUartData();

            V_WaitResponceTime = 0;

            return C_Success;

    }

    else

    {

        return C_Waiting;

    }


}


/*

 函数功能:等待应答

 输入参数:

 输出参数:

           C_Success  成功

           C_Fail     失败

**/

uint8_t F_Wait_ACK(void)

{

    V_WaitResponceTime = 0;

    while(1)

    {

        if(C_Success == F_WaitResponce(0,C_ACK,30))

        {

            UART2_SendByte(C_ACK);

            return C_Success;

        }

        if(C_Success == F_WaitResponce(0,C_NACK,30))

        {

            return C_Fail;

        }   

    }

}


1.获取命令和版本号


/*

 函数功能:获取BootLoader版本号

 返回参数:C_Fail      失败

           C_Success   成功

 注意:    函数执行完,返回成功。接收数组中应该有参数,

           0x05、0x13、0x00、0x11、0x21、0x31、0x43

**/



uint8_t F_CheckVersion(void)

{

    UART2_SendByte(C_Get);

    UART2_SendByte(~C_Get);

    if(F_Wait_ACK() == C_Fail) return C_Fail;

    UART2_SendByte(C_ACK);//0x05

    UART2_SendByte(C_ACK);//0x13

    UART2_SendByte(C_ACK);//0x00

    UART2_SendByte(C_ACK);//0x11

    UART2_SendByte(C_ACK);//0x21

    UART2_SendByte(C_ACK);//0x31

    UART2_SendByte(C_ACK);//0x43

    if(F_Wait_ACK() == C_Fail) return C_Fail;

    return C_Success;

}


写到这里,就能正确获取,指令,版本号。 

值得注意的地方是,在支持文档中,要求从机发的所有字节都应该有应答,所以当主机发从机命令,从机发了一个应答,主机应该回一个应答(刚开始我就在这里犯错,没有回应答,造成后面发命令就非应答)。


Reply mode

The host must reply to all the bytes sent from the bootloader. 


2.读内存经由UART命令 

主机发送给STM8字节如下: 

字节1-2: 0x11(命令号) + 0xEE(补码) 

字节3-6: 开始地址(32位) 

Byte 3 = MSB 

Byte 6 = LSB 

字节7: 校验和 = XOR (字节3.4.5.6) 

字节8: 要读的字节数-1(0 <= N <= 255) 

字节9: 校验码(字节8的补码) 

注意:要读的字节数-1(0 <= N <= 255),因为数组总是从0开始排序。读超过256个数要重新给地址。


3.擦除内存和写内存命令 

在执行这两个操作前要进行写RAM操作,不然直接操作就等不到应答。 

参考写RAM链接 

通过别人写的文档,发现写入数据才能操作。但实际把数据抄进来,我的这两个操作还是不能正确。之后通过STMFlashLoader Demo.exe 直接用两个串口接收,发现数据是不一样的,可见每一款不同型号的MCU写入的数据都不一样,具体的数据要通过抓取STMFlashLoader Demo.exe和MCU通讯的数据确定。这里注意,执行擦除,写内存,每一次都进行了写RAM,实际操作,写一次就好。


/*

 函数功能: Write memory

 传入参数:  V_SlaveWriteAdress  写入从机的地址

            V_SendByteCount     写入多少字节

            arr                 写入从机的的数组首地址

 返回:     成功1,失败0

*/


uint8_t F_ProgramOneBlock(uint32_t V_SlaveWriteAdress,uint8_t V_SendByteCount,uint8_t * arr)

{

    uint8_t V_Address1,V_Address2,V_Address3,V_Address4;

    UART2_SendByte(C_WriteMemory);

    UART2_SendByte(~C_WriteMemory);

    if(F_Wait_ACK() == C_Fail) return 0;


    V_Address1 = V_SlaveWriteAdress >>24;

    V_Address2 = (V_SlaveWriteAdress &0x00FF0000) >>16;

    V_Address3 = (V_SlaveWriteAdress &0x0000FF00) >>8;

    V_Address4 =  V_SlaveWriteAdress &0x000000FF;

    UART2_SendByte(V_Address1);// 

    UART2_SendByte(V_Address2);// 

    UART2_SendByte(V_Address3);// 

    UART2_SendByte(V_Address4);// 

    UART2_SendByte(V_Address1 ^ V_Address2 ^ V_Address3 ^ V_Address4);//    

    if(F_Wait_ACK() == C_Fail) return 0;


    //发多少字节数据

    UART2_SendByte(V_SendByteCount-1);

    //发送有用的数据

    uint8_t V_Checksum = V_SendByteCount-1;

    for(uint8_t i= 0;i    {


        UART2_SendByte(*(arr+i));

        V_Checksum ^=*(arr+i) ;

    }

    //发checksum,128字节的校验和,逐字节亦或

    UART2_SendByte(V_Checksum); // checksum 


    if(F_Wait_ACK() == C_Fail) return 0;

    return 1;

}


/*

* 第129个数据是checksum,是128^C_RAM_Arr1[0]...^C_RAM_Arr1[127]

* 31 CE 79 00 00 00 A0 A0 79 7F 写第一组字符串

* 31 CE             write data

* 79                ACK

* 00 00 00 A0       4byte adress

* A0                checksum,0x00 ^,0x00 ^,0x00 ^,0xA0

* 79                ACK

[1] [2]
关键字:STM8S  自带BootLoader 引用地址:使用STM8S自带BootLoader_2

上一篇:基于STM8S003的无源蜂鸣器播放音乐
下一篇:STM8S IO最快翻转速度

推荐阅读最新更新时间:2024-11-21 22:06

STM8S 定时器1 输入捕获
输入捕捉的引脚要实现设定,使用stvp + stlink 就可以设置,否则无法进入中断。 然后下面是代码: C语言: Codee#11818 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 实验平台: STM8S103F2P6 FM 接收实验核心板 + 硬件 : STM8S103F2P6 + 开发平台: IAR For STM8 1.10 + 仿真器 : ST-Link + 日期 : 2010-6-28 +++++++++++++++++++++++++++++++++++++++++++++++++
[单片机]
<font color='red'>STM8S</font> 定时器1 输入捕获
STM8不用手动复位进入自带Bootloader方法(串口下载)
除非STM8片子的空的,如果复位运行的是自带Bootloader,而且要通过串口下载程序的话,必须在1s内点击上位机,要不然就运行用户程序了。 这一步很麻烦,所以想把它给省掉。 后来发现上位机Flash Loader Demonstrator在启动画面点击Next后,会先从串口的DTR、RTS输出一个大概100多毫秒的脉冲,TTL电平就是负脉冲了,之后才会和单片机通信。 所以只要按照下面的图接线,如果单片机复位运行的是自带Bootloader,只要在Flash Loader Demonstrator启动画面点击Next,软件就会复位单片机,不用自己手动复位再点击Next就可以和单片机通信了。 还有就是下载STM8S或STM8
[单片机]
STM8不用手动复位进入<font color='red'>自带</font><font color='red'>Bootloader</font>方法(串口下载)
关于STM8S低功耗电源管理
在后台陆续收到一些关于STM8S低功耗的问题,今天就写一下低功耗相关的内容。 1STM8S功耗来源 STM8S功耗分静态功耗和动态功耗。 静态功耗:主要由晶体管的偏置电流和漏电流产生。 动态功耗:取决于电源电压和工作时钟频率。 在CMOS逻辑电路以一定时钟频率运行时,静态功耗与动态功耗相比是可以忽略的。但在一些低功耗模式下,时钟不再运行,此时静态功耗是主要的功耗源。 因此,功耗主要取决于: 1.微控制器单元(MCU)的芯片面积:所采用的工艺,晶体管的数量,片上集成和使用的模拟功能/外设。 2.MCU电源电压:CMOS逻辑电路中消耗的电流与电源电压的平方成正比。因此,可以通过降低供电电压来降低功耗。 3.时钟频率:在不要求进
[单片机]
关于<font color='red'>STM8S</font>低功耗电源管理
stm8s输入捕获
输入捕获,简而言之,即 记录信号到来时刻的CNTR的值,然后把该值传给CCR。下面以PC1为例,代码如下: TIM1_CR1_DIR = 0;//计数器向上计数 TIM1_IER_UIE = 1;//使能TIM1溢出中断 TIM1_PSCRH = 0x00; TIM1_PSCRL = 0x05; //配置TIM1为6分频- 0.75us记一次数 TIM1_ARRH = 0xFF; TIM1_ARRL = 0xFF; //自动重装载的值,49ms中断 TIM1_CNTRH = 0xFF; TIM1_CNTRL = 0xFF; TIM1_CCER1_CC1E = 0;//禁止捕获使能
[单片机]
STM8S(105K4)使用笔记——独立看门狗IWDG的基础配置
0、独立看门狗的使用 独立看门狗基于低速内部RC振荡器(LSI)运行。 若LSI运行正常,当主程序发生错误时,无法重置看门狗计数器,独立看门狗将会产生复位标志位并重启。 由于独立看门狗基于LSI运行,与主程序、大部分外设相独立,这能最大限度保证独立看门狗的功能正常运行。 1、使能独立看门狗 /* 使能独立看门狗 (低速内部RC振荡器(LSI)将会被硬件使能) */ IWDG- KR = (uint8_t)0xCC; 注意!一旦独立看门狗被使能将无法禁用! 如果你需要使用stm8s的低功耗模式,同时需要使用看门狗复位功能,请选择窗口看门狗! 2、配置分频因子与重装载值 解除PR、RLR寄存器写保护 /* P
[单片机]
stm8s单片机实现多通道转换
今天在使用stm8s单片机的AD功能,单片机上有AN0到AN9十个通道。想只用其中的三路AN5到AN7。 //ADC初始化 void ADC_Init(void) { ADC_CR1 = 0x50; ADC_CR2 = 0x38; ADC_TDRL = 0xE0; //禁止施密特触发 } unsigned int Read_ADC_Temp(unsigned channel) { unsigned int i,ADtemp; ADC_Init(); //ADC_CSR = 0x00; ADC_CSR = channel; ADC_CR1 = 0x01; // CR1寄存器的最低位置1,使能ADC转换 for(i = 0;
[单片机]
stm8s的assert_param()的说明
STM8S的程序,子程序都有assert_param(....),如下:这句到底有什么用呢???把它删了应该可以的吗?? void TIM1_TimeBaseInit(u16 TIM1_Prescaler, TIM1_CounterMode_TypeDef TIM1_CounterMode, u16 TIM1_Period, u8 TIM1_RepetitionCounter) { /* Check parameters */ assert_param(IS_TIM1_COUNTER_MODE_OK(TIM1_CounterMode)); ...... }
[单片机]
关于STM8S的halt状态及唤醒
简介:有个项目用了STM8S103F3,因是电池供电,需要进入halt状态并使用GPIO外部唤醒,因是初次使用STM8S,走了不少弯路,将过程记录下来,好让和我一样的初次接触STM8S的人有个启发。 现象:进不了HALT状态 硬件环境:使用PA1、PA2、PD2、PD5作为外部中断输入,来唤醒MCU。使用PD4作为输出,使用PD3作为AD转换口。 编程思路: 1、初始化系统(时钟、gpio)部分代码如下: void JG_GPIO_Init(void) { PA_DDR = 0xf9; PA_CR1 = 0x00; PA_CR2 = 0x06; //pa1、pa2中断 PB_DDR = 0x
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved