搜索
bottom↓
回复: 23

PID + Protothreads 做的一个充电器 (完整的项目)

  [复制链接]

出0入0汤圆

发表于 2019-3-13 18:06:57 | 显示全部楼层 |阅读模式
1 >> 项目PID参考了以下帖子: 关于PID我没有什么可以说的,因为我是拿来就用,只调整 K_P ,K_I ,K_D 三个参数,实测效果可以.

https://www.amobbs.com/thread-5556400-1-1.html

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 这个文件夹 里有原理图和需求文档 (备注:代码有些地方与文档并不一致)

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;                               //返回数据
}




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2019-3-13 18:10:00 | 显示全部楼层
占楼 >> 项目通过编译 需要安装 SN-Link_Driver for Keil C51_V2.00.34

出0入0汤圆

发表于 2019-3-13 18:17:23 | 显示全部楼层
不错.. 有没有电路图..这样看,,很慌.

出0入0汤圆

发表于 2019-3-13 18:31:59 | 显示全部楼层
自整定怎么弄,我弄的不行

出0入0汤圆

 楼主| 发表于 2019-3-13 18:56:00 | 显示全部楼层
sweet_136 发表于 2019-3-13 18:17
不错.. 有没有电路图..这样看,,很慌.

4 >> 在 _isch 这个文件夹 里有原理图和需求文档 (备注:代码有些地方与文档并不一致)

出0入42汤圆

发表于 2019-3-13 19:14:35 | 显示全部楼层
感谢楼主分享。。。

出75入90汤圆

发表于 2019-3-13 19:47:36 | 显示全部楼层
很好的资料,谢谢分享。
可惜我还不懂什么是PID,为什么充电器要用PID?哪位大哥能赐教一下。

出0入0汤圆

发表于 2019-3-13 19:53:46 来自手机 | 显示全部楼层
主要是有电路吗

出0入0汤圆

发表于 2019-3-13 19:55:58 | 显示全部楼层
楼主牛比,我是来学习的,留下足迹1个。。。

出0入0汤圆

发表于 2019-3-13 21:00:04 | 显示全部楼层
mathison 发表于 2019-3-13 18:10
占楼 >> 项目通过编译 需要安装 SN-Link_Driver for Keil C51_V2.00.34

接的俄罗斯项目?居然是俄语

出0入0汤圆

发表于 2019-3-13 21:36:39 | 显示全部楼层
很好的资料

出0入0汤圆

 楼主| 发表于 2019-3-13 23:32:35 | 显示全部楼层
mubei 发表于 2019-3-13 21:00
接的俄罗斯项目?居然是俄语

是的 俄罗斯 把一些低端的 cost down的 产品扔给我们做

(一些低端的 低成本的产品,外国人根本没法跟我们竞争,可惜啊,搞贸易战)

本来是 计划用两路PWM 来提高 充电效率的 硬件工程师没有细看 SN8F5702 的 datasheet  PWM没法输出死区,松翰故意这么挖坑。

出0入0汤圆

发表于 2019-3-14 09:08:25 | 显示全部楼层
Protothreads mark!

出0入0汤圆

发表于 2019-3-14 09:21:06 | 显示全部楼层
很好的资料,谢谢分亨!

出0入0汤圆

发表于 2019-3-14 09:38:15 | 显示全部楼层
很慌  看了一下是个锂电池充电器

出1310入193汤圆

发表于 2019-3-25 08:29:53 | 显示全部楼层
PID + Protothreads 做的一个充电器   原理图图片形式发上来就超级棒

出0入0汤圆

发表于 2019-3-25 11:46:27 | 显示全部楼层
谢谢分亨!

出0入0汤圆

发表于 2019-3-25 13:55:01 | 显示全部楼层
感谢分享,做得漂亮。
精神值得鼓励。

出0入0汤圆

发表于 2019-3-25 14:23:34 | 显示全部楼层
谢谢分享,!我一位只有温控才有PID控制呢

出0入0汤圆

发表于 2019-3-25 16:12:00 | 显示全部楼层

好资料,谢谢分亨

出0入8汤圆

发表于 2019-6-21 16:02:18 | 显示全部楼层
mark,最近也在看protothread,向LZ学习下。

出0入0汤圆

发表于 2019-10-21 13:53:19 | 显示全部楼层
谢谢楼主分享,学习学习!~

出0入0汤圆

发表于 2019-10-24 22:04:39 | 显示全部楼层
楼主牛比

出0入0汤圆

发表于 2019-10-25 10:03:32 | 显示全部楼层
mathison 发表于 2019-3-13 18:10
占楼 >> 项目通过编译 需要安装 SN-Link_Driver for Keil C51_V2.00.34

可以把timer_set和timer_expired函数贴出来一下吗,学习一下实现的思路
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-20 12:44

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表