【转】松翰单片机+PID + Protothreads 做的一个充电器 (完整的项目)

admin 2019-3-14 2826

1 >> 项目PID: 关于PID我没有什么可以说的,因为我是拿来就用,只调整 K_P ,K_I ,K_D 三个参数,实测效果可以.


2 >> Protothreads 使用的是 康奈尔大学ECE4760课程中的Protothreads  (备注 gSysTick++; //1ms  所有的时间片 基于此)

修正了其中的一个bug:

这是原版的:

#ifdef MX250
#define PT_YIELD_TIME_msec(delay_time)  \
    do { static unsigned int time_thread ;\
    time_thread = gSysTick + (delay_time) ; \
    PT_YIELD_UNTIL(pt, (gSysTick >= time_thread)); \
    } while(0);
#endif

这是修正后的:

#if 1
#define PT_YIELD_TIME_msec(delay_time)  \
    do { static volatile unsigned int time_thread ;\
    time_thread = gSysTick; \
    PT_YIELD_UNTIL(pt, ((unsigned int)(gSysTick - time_thread) >= (unsigned int)(delay_time))); \
    } while(0);
#endif

3 >>  考虑到这个案子也没有什么没有太难的东西,而且这个只是第一次送样的代码(离产品还有一些距离),所以就当是对无私的热心地坛友的一声谢谢. (如果认识我们老板或者这个案子的客户,请保持沉默,别打我小报告)

4 >> 在 _isch 这个文件夹 里有原理图和需求文档 (备注:代码有些地方与文档并不一致)。项目通过编译 需要安装 SN-Link_Driver for Keil C51_V2.00.34。

5>> 这个案子并没有 按键 和 I2C,我把这两个文件也打包一起放上来,希望大家能用得上:

//app_key.c
#include "app_cfg.h"
#include "app_global.h"
#include "app_timer.h"
#ifdef UART1_EN
#include "sn8f5702_uart.h"
#endif
#define KEY_GLOBALS
#include "app_key.h"
//#define DBG  uart_printf
code BYTE GpioKeyEvent[][5] =
{
    //PDS(按键开始)      SPR(短按松开)      CPS(长按开始)       CPH(长按保持)           CPR(长按松开)
    {MSG_NONE,           MSG_MODE,          MSG_POWER_ON,       KEY_POWER_LONG,         KEY_POWER_LONG_BREAK},  //K1
    {MSG_NONE,           MSG_LIGHT,         MSG_LIGHT_CPS,      MSG_LIGHT_CPH,          MSG_LIGHT_CPR       },  //K2
};
TIMER idata gpioKeyWaitTimer;
//TIMER gpioKeyScanTimer;
GPIO_KEY_STATE idata GpioKeyState;
void GpioKeyInit(void)
{
    P_KEY_POWER_INPUT;
    GpioKeyState = GPIO_KEY_STATE_IDLE;
    //timer_set(&gpioKeyScanTimer, 0);
}
static u8_t GetGpioKeyIndex(void)
{
    u8_t KeyIndex = 0xFF;
    if(P_KEY_POWER == 0)
    {
        KeyIndex = 0;
    }
    return KeyIndex;
}
KEY_EVENT GpioKeyScan(void)
{
    static  unsigned char idata PreKeyIndex = 0xFF;
    BYTE KeyIndex;
    KeyIndex = GetGpioKeyIndex();
    switch(GpioKeyState)
    {
        case GPIO_KEY_STATE_IDLE:
            if(KeyIndex == 0xFF)
            {
                return MSG_NONE;
            }
            PreKeyIndex = KeyIndex;
            timer_set(&gpioKeyWaitTimer, GPIO_KEY_JTTER_TIME);
            //DBG(("GOTO JITTER!\n"));
            GpioKeyState = GPIO_KEY_STATE_JITTER;
        case GPIO_KEY_STATE_JITTER:
            if(PreKeyIndex != KeyIndex)
            {
                //DBG(("GOTO IDLE Because jitter!\n"));
                GpioKeyState = GPIO_KEY_STATE_IDLE;
            }
            else if(timer_expired(&gpioKeyWaitTimer))
            {
                //DBG(("GOTO PRESS_DOWN!\n"));
                //P_KEY_OUT = 0;
                //Uart1_PutChar(0xA1);
                timer_set(&gpioKeyWaitTimer, GPIO_KEY_CP_TIME);
                GpioKeyState = GPIO_KEY_STATE_PRESS_DOWN;
                return GpioKeyEvent[PreKeyIndex][0];//PDS(按键开始)
            }
            break;
        case GPIO_KEY_STATE_PRESS_DOWN:
            if(PreKeyIndex != KeyIndex)
            {
                //DBG(("ADC KEY SP!*****\n"));
                //P_KEY_OUT = 1;
                //Uart1_PutChar(0xA2);
                GpioKeyState = GPIO_KEY_STATE_IDLE;
                return GpioKeyEvent[PreKeyIndex][1]; //SPR(短按松开)
            }
            else if(timer_expired(&gpioKeyWaitTimer))
            {
                //DBG(("ADC KEY CP!********\n"));
                //P_KEY_OUT = 1;
                //Uart1_PutChar(0xA3);
                //P_LED_R_ON;
                timer_set(&gpioKeyWaitTimer, GPIO_KEY_CPH_TIME);
                GpioKeyState = GPIO_KEY_STATE_CP;
                return GpioKeyEvent[PreKeyIndex][2];  //CPS(长按开始)
            }
            break;
        case GPIO_KEY_STATE_CP:
            if(PreKeyIndex != KeyIndex)
            {
                //DBG(("ADC KEY CPR!*************\n"));
                //Uart1_PutChar(0xA4);
                //P_LED_R_OFF;
                GpioKeyState = GPIO_KEY_STATE_IDLE;
                return GpioKeyEvent[PreKeyIndex][4]; //CPR(长按松开)
            }
            else if(timer_expired(&gpioKeyWaitTimer))
            {
                //DBG(("ADC KEY CPH!*************\n"));
                timer_set(&gpioKeyWaitTimer, GPIO_KEY_CPH_TIME);
                return GpioKeyEvent[PreKeyIndex][3]; // CPH(长按保持)
            }
            break;
        default:
            GpioKeyState = GPIO_KEY_STATE_IDLE;
            break;
    }
    return MSG_NONE;
}
//bsp_i2c.c
#include "sn8f5702.h"
#include "app_cfg.h"
#include "app_global.h"
#ifdef UART1_EN
#include "sn8f5702_uart.h"
#endif
#include "bsp_i2c.h"
#define I2C_Delay()     _dly_1us(1)
#define GET_ACK_TIME                    250
/******************************************************************************************
*函数名称:  void I2C_Idle(void)
*入口参数:  无
*出口参数:  无
*函数功能:  I2C总线空闲
******************************************************************************************/
void I2C_Idle(void)
{
    P_I2C_SCL_OUTPUT;
    P_I2C_SCL = 1;
    P_I2C_SDA_OUTPUT;
    P_I2C_SDA = 1;
}
/******************************************************************************************
*函数名称:  void I2C_Start(void)
*入口参数:  无
*出口参数:  无
*函数功能:  I2C通信启始
            SDA 1->0 while SCL High
******************************************************************************************/
void I2C_Start(void)
{
    P_I2C_SCL_OUTPUT;
    P_I2C_SCL = 1;
    P_I2C_SDA_OUTPUT;
    P_I2C_SDA = 1;
    I2C_Delay();
    P_I2C_SDA = 0;
    I2C_Delay();
    P_I2C_SCL = 0;
}
/******************************************************************************************
*函数名称:  void I2C_Stop(void)
*入口参数:  无
*出口参数:  无
*函数功能:  I2C通信结束
            SDA 0->1 while SCL High
******************************************************************************************/
void I2C_Stop(void)
{
    P_I2C_SCL_OUTPUT;
    P_I2C_SCL = 0;
    P_I2C_SDA_OUTPUT;
    P_I2C_SDA = 0;
    I2C_Delay();
    P_I2C_SCL = 1;
    I2C_Delay();
    P_I2C_SDA = 1;
    I2C_Delay();
}
/**
  * @brief  This function checks ACK/NACK from I2C slave.
  * @param  None
  * @return None
  */
boolean I2C_ChkAck(void)
{
    boolean Ack;
    unsigned char GetAckTime = GET_ACK_TIME;                  //返回ACK信号延时等待时间
    P_I2C_SDA_INPUT;       //Allow slave to send ACK
    P_I2C_SCL = 0;        //slave send ACK
    P_I2C_SCL = 1;
    while(P_I2C_SDA && (--GetAckTime));
    Ack = (!P_I2C_SDA);     //Get ACK from slave
    P_I2C_SCL = 0;
    P_I2C_SDA_OUTPUT; // add by k.s
    return Ack;
}
/******************************************************************************************
*函数名称:  boolean I2C_WriteByte(unsigned char SendByte)
*入口参数:  unsigned char SendByte--发送的字节
*出口参数:  无
*函数功能:  向I2C总线发送一个字节
*This function send one byte to I2C slave.
******************************************************************************************/
boolean I2C_WriteByte(unsigned char SendByte)
{
    unsigned char i = 8;
    P_I2C_SDA_OUTPUT;
    P_I2C_SCL = 0;   //设置I2C_SDA为输出
    while(i--)       //I2C_SDA脚从高位至低位发送数据
    {
        if(SendByte & 0x80)                  /* MSB output first */
        {
            P_I2C_SDA = 1;
        }
        else
        {
            P_I2C_SDA = 0;
        }
        SendByte <<= 1;
        P_I2C_SCL = 1;                            //拉高I2C_SCL
        I2C_Delay();
        P_I2C_SCL = 0;                            //拉低I2C_SCL,以允许I2C_SDA脚w位数据发生变化
    }
    return I2C_ChkAck();
}
/******************************************************************************************
*函数名称:  unsigned char  I2C_ReadByte(void)
*入口参数:  无
*出口参数:  unsigned char  RecByte--读取的字节
*函数功能:  向I2C总线读取一个字节
******************************************************************************************/
void I2C_SendNoAck(void)
{
    P_I2C_SDA = 1;
    P_I2C_SCL = 1;
    I2C_Delay();
    P_I2C_SCL = 0;
}
unsigned char I2C_ReadByte(void)
{
    unsigned char i = 8;
    unsigned char Dat = 0;
    P_I2C_SDA_INPUT;                          //设置I2C_SDA为输入
    while(i--)
    {
        P_I2C_SCL = 1;                                //拉高I2C_SCL
        I2C_Delay();
        Dat <<= 1;
        if(P_I2C_SDA)
        {
            Dat |= 0x01;
        }
        P_I2C_SCL = 0;                                //拉低I2C_SCL
        I2C_Delay();
    }
    P_I2C_SDA_OUTPUT;                                      //设置I2C_SDA为输出
    return  Dat;                               //返回数据
}



上传的附件:
最新回复 [0]
返回