Codoox 发表于 2018-8-19 17:07:07

STC15F2K60S2 P42管脚驱动能力弱问题

电路如下,P42控制NMOS管AO3416,

管脚配置成推挽输出:
P4M1&= ~0x04;// P42 输出 红外
P4M0|=    0x04;

问题如下:

1.目前手里有两批芯片,老批次的测得P42管脚输出高时,电压能拉到2.7V左右,电路能正常工作所以一直未发现这个问题;新批次的芯片P42管脚输出高时,实测电压接0V。

2.将P42管脚断开,输出拉高拉低都正常;连上10K电阻即出现拉不高的现象。万用表测试P42对地阻值确实是10K,与边上管脚也不存在短路现象。把10K电阻换成100K能上拉到2.5V,换成300K电阻,输出能正常拉高拉低。

3.目前实验了10多台都是这样,可以肯定的是这个管脚驱动能力不够;按手册写的即使工作在双向模式也能提供150uA电流,驱动一个100K电阻足够了;而且目前是配置成推挽输出,不应该存在驱动能力不够的情况。

这个管脚有什么特殊之处吗?操作的不对?

饭桶 发表于 2018-8-19 18:29:34

和别的引脚对比一下;自己加个4K7电阻上拉试试。

饭桶 发表于 2018-8-19 18:30:06

检查一下单片机的电源地是否连接正确!

Codoox 发表于 2018-8-19 18:48:45

饭桶 发表于 2018-8-19 18:30
检查一下单片机的电源地是否连接正确!

电源地也没有问题,别的功能都正常,目前就发现这个管脚拉不高。现在是把下拉电阻统一换成470K了,能正常工作。
现在不知道是什么原因造成的,怕存在隐患。

su33691 发表于 2018-8-19 19:35:55

虽然STC宣称能提供150uA电流,我还是更相信INTEL的数据,按60UA设计。

1826772880 发表于 2018-8-19 19:45:51

不应该是P4M1= 0x00;// P42 输出 红外
            P4M0=0x04;

Codoox 发表于 2018-8-19 19:53:24

1826772880 发表于 2018-8-19 19:45
不应该是P4M1= 0x00;// P42 输出 红外
            P4M0=0x04;

你这样就把P4所有的管脚都设成推挽输出了,上面的代码仅仅是把P42管脚设成推挽

1826772880 发表于 2018-8-19 19:54:14

Codoox 发表于 2018-8-19 19:53
你这样就把P4所有的管脚都设成推挽输出了,上面的代码仅仅是把P42管脚设成推挽 ...

你需要冷静看数据手册

Codoox 发表于 2018-8-19 19:58:01

su33691 发表于 2018-8-19 19:35
虽然STC宣称能提供150uA电流,我还是更相信INTEL的数据,按60UA设计。

双向口:
手册上写的拉电流270uA,由于制造误差,实际为270uA~150uA。
而且用100K电阻,5V也就才50uA。

推挽输出:
手册写的是可达20mA。

sfes 发表于 2018-8-19 20:04:20

6楼是对的

Codoox 发表于 2018-8-19 20:22:43

1826772880 发表于 2018-8-19 19:54
你需要冷静看数据手册

还是没明白,我这样设置有什么错吗?

1826772880 发表于 2018-8-19 20:25:34

Codoox 发表于 2018-8-19 20:22
还是没明白,我这样设置有什么错吗?

你这个操作是自己研究的还是抄哪里的?先试试我贴的,行的话再继续讨论。

Codoox 发表于 2018-8-19 20:41:09

1826772880 发表于 2018-8-19 20:25
你这个操作是自己研究的还是抄哪里的?先试试我贴的,行的话再继续讨论。 ...

按位与,按位或,不都是这么操作的吗?

这样操作有什么错请明示,谢谢!

我翻了一下STC的手册有这样的写法:

P3M1 &=~(1<<4); //P3.4设置为推挽输出
P3M0 |=(1<<4);

上面的1<<4 不应该 = 0x10 吗?

同理第2管脚不应该是 1<<2 = 0x04 吗?

1826772880 发表于 2018-8-19 20:45:06

Codoox 发表于 2018-8-19 20:41
按位与,按位或,不都是这么操作的吗?

这样操作有什么错请明示,谢谢!


错不错我没精力研究{:lol:},我不明白的是为啥要要运算,而不是直接赋值?

Codoox 发表于 2018-8-19 20:52:04

1826772880 发表于 2018-8-19 20:45
错不错我没精力研究,我不明白的是为啥要要运算,而不是直接赋值? ...

直接赋值的话会把别的管脚状态也改掉,按位与或可以保持别的管脚不变,只改变这一个管脚的配置。

这不是很常用的操作方式吗?如果说这种操作方式有错,还是我用的不对,请指正

1826772880 发表于 2018-8-19 20:58:41

Codoox 发表于 2018-8-19 20:52
直接赋值的话会把别的管脚状态也改掉,按位与或可以保持别的管脚不变,只改变这一个管脚的配置。

这不是 ...

这样,
1代码问题:
你呢先按照直接赋值试试,可以推挽呢那就是你代码问题,然后呢再请教高手研究下代码哪里有问题。
2芯片问题:
直接赋值不行呢再向STC问芯片问题。
我没对管脚配置用过运算,这个不敢乱说{:lol:}

cc224 发表于 2018-8-19 22:03:29

是不是有别的地方误设置了管脚状态?

rain73 发表于 2018-8-19 23:13:14

1826772880 发表于 2018-8-19 20:45
错不错我没精力研究,我不明白的是为啥要要运算,而不是直接赋值? ...

用表达式运算直观一点,这个没有问题。
运算是由编译器运算的,编译好后的代码和直接赋值的结果是一样的。
好久没玩51了。

chess01 发表于 2018-8-20 09:04:42

你的电路有问题,单片机IO口驱动MOS管应该串一个100欧的电阻,如果因为这个电阻导致关断不够迅速,再在电阻上反并一个二极管

LM1876 发表于 2018-8-20 09:10:39

chess01 发表于 2018-8-20 09:04
你的电路有问题,单片机IO口驱动MOS管应该串一个100欧的电阻,如果因为这个电阻导致关断不够迅速,再在电阻上 ...

和电路没关系,就是他设置问题

Codoox 发表于 2018-8-20 09:14:42

LM1876 发表于 2018-8-20 09:10
和电路没关系,就是他设置问题

确实是设置问题,后面有个别的管脚错配成P42了

LM1876 发表于 2018-8-20 09:15:07

#include        "STC15_GPIO.h"
unsigned char GPIO_Inilize(unsigned char GPIO, GPIO_InitTypeDef *GPIOx)
{
        if(GPIO > GPIO_P7)                                return 1;        //空操作
        if(GPIOx->Mode > GPIO_OUT_PP)        return 2;        //错误

        if(GPIO == GPIO_P0)
        {
                if(GPIOx->Mode == GPIO_PullUp)                P0M1 &= ~GPIOx->Pin,        P0M0 &= ~GPIOx->Pin;       //上拉准双向口
                if(GPIOx->Mode == GPIO_HighZ)                P0M1 |=GPIOx->Pin,        P0M0 &= ~GPIOx->Pin;       //浮空输入
                if(GPIOx->Mode == GPIO_OUT_OD)                P0M1 |=GPIOx->Pin,        P0M0 |=GPIOx->Pin;       //开漏输出
                if(GPIOx->Mode == GPIO_OUT_PP)                P0M1 &= ~GPIOx->Pin,        P0M0 |=GPIOx->Pin;       //推挽输出
        }
        if(GPIO == GPIO_P1)
        {
                if(GPIOx->Mode == GPIO_PullUp)                P1M1 &= ~GPIOx->Pin,        P1M0 &= ~GPIOx->Pin;       //上拉准双向口
                if(GPIOx->Mode == GPIO_HighZ)                P1M1 |=GPIOx->Pin,        P1M0 &= ~GPIOx->Pin;       //浮空输入
                if(GPIOx->Mode == GPIO_OUT_OD)                P1M1 |=GPIOx->Pin,        P1M0 |=GPIOx->Pin;       //开漏输出
                if(GPIOx->Mode == GPIO_OUT_PP)                P1M1 &= ~GPIOx->Pin,        P1M0 |=GPIOx->Pin;       //推挽输出
        }
        if(GPIO == GPIO_P2)
        {
                if(GPIOx->Mode == GPIO_PullUp)                P2M1 &= ~GPIOx->Pin,        P2M0 &= ~GPIOx->Pin;       //上拉准双向口
                if(GPIOx->Mode == GPIO_HighZ)                P2M1 |=GPIOx->Pin,        P2M0 &= ~GPIOx->Pin;       //浮空输入
                if(GPIOx->Mode == GPIO_OUT_OD)                P2M1 |=GPIOx->Pin,        P2M0 |=GPIOx->Pin;       //开漏输出
                if(GPIOx->Mode == GPIO_OUT_PP)                P2M1 &= ~GPIOx->Pin,        P2M0 |=GPIOx->Pin;       //推挽输出
        }
        if(GPIO == GPIO_P3)
        {
                if(GPIOx->Mode == GPIO_PullUp)                P3M1 &= ~GPIOx->Pin,        P3M0 &= ~GPIOx->Pin;       //上拉准双向口
                if(GPIOx->Mode == GPIO_HighZ)                P3M1 |=GPIOx->Pin,        P3M0 &= ~GPIOx->Pin;       //浮空输入
                if(GPIOx->Mode == GPIO_OUT_OD)                P3M1 |=GPIOx->Pin,        P3M0 |=GPIOx->Pin;       //开漏输出
                if(GPIOx->Mode == GPIO_OUT_PP)                P3M1 &= ~GPIOx->Pin,        P3M0 |=GPIOx->Pin;       //推挽输出
        }
        if(GPIO == GPIO_P4)
        {
                if(GPIOx->Mode == GPIO_PullUp)                P4M1 &= ~GPIOx->Pin,        P4M0 &= ~GPIOx->Pin;       //上拉准双向口
                if(GPIOx->Mode == GPIO_HighZ)                P4M1 |=GPIOx->Pin,        P4M0 &= ~GPIOx->Pin;       //浮空输入
                if(GPIOx->Mode == GPIO_OUT_OD)                P4M1 |=GPIOx->Pin,        P4M0 |=GPIOx->Pin;       //开漏输出
                if(GPIOx->Mode == GPIO_OUT_PP)                P4M1 &= ~GPIOx->Pin,        P4M0 |=GPIOx->Pin;       //推挽输出
        }
        if(GPIO == GPIO_P5)
        {
                if(GPIOx->Mode == GPIO_PullUp)                P5M1 &= ~GPIOx->Pin,        P5M0 &= ~GPIOx->Pin;       //上拉准双向口
                if(GPIOx->Mode == GPIO_HighZ)                P5M1 |=GPIOx->Pin,        P5M0 &= ~GPIOx->Pin;       //浮空输入
                if(GPIOx->Mode == GPIO_OUT_OD)                P5M1 |=GPIOx->Pin,        P5M0 |=GPIOx->Pin;       //开漏输出
                if(GPIOx->Mode == GPIO_OUT_PP)                P5M1 &= ~GPIOx->Pin,        P5M0 |=GPIOx->Pin;       //推挽输出
        }
        if(GPIO == GPIO_P6)
        {
                if(GPIOx->Mode == GPIO_PullUp)                P6M1 &= ~GPIOx->Pin,        P6M0 &= ~GPIOx->Pin;       //上拉准双向口
                if(GPIOx->Mode == GPIO_HighZ)                P6M1 |=GPIOx->Pin,        P6M0 &= ~GPIOx->Pin;       //浮空输入
                if(GPIOx->Mode == GPIO_OUT_OD)                P6M1 |=GPIOx->Pin,        P6M0 |=GPIOx->Pin;       //开漏输出
                if(GPIOx->Mode == GPIO_OUT_PP)                P6M1 &= ~GPIOx->Pin,        P6M0 |=GPIOx->Pin;       //推挽输出
        }
        if(GPIO == GPIO_P7)
        {
                if(GPIOx->Mode == GPIO_PullUp)                P7M1 &= ~GPIOx->Pin,        P7M0 &= ~GPIOx->Pin;       //上拉准双向口
                if(GPIOx->Mode == GPIO_HighZ)                P7M1 |=GPIOx->Pin,        P7M0 &= ~GPIOx->Pin;       //浮空输入
                if(GPIOx->Mode == GPIO_OUT_OD)                P7M1 |=GPIOx->Pin,        P7M0 |=GPIOx->Pin;       //开漏输出
                if(GPIOx->Mode == GPIO_OUT_PP)                P7M1 &= ~GPIOx->Pin,        P7M0 |=GPIOx->Pin;       //推挽输出
        }
       
        return 0;        //成功
}

#include "Port.h"
#include "..\Lib\STC15_GPIO.h"

       
void GPIO_ConfigInit(void)        //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
{
        GPIO_InitTypeDef        GPIO_InitStructure;                        //结构定义
//*********************指示灯***************************
        //LED_INGpin
        GPIO_InitStructure.Pin= GPIO_Pin_6;                    //P1.6 管脚
        GPIO_InitStructure.Mode = GPIO_OUT_PP;                        //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
        GPIO_Inilize(GPIO_P1,&GPIO_InitStructure);                //
//        //LED_INRpin
//        GPIO_InitStructure.Pin= GPIO_Pin_4;                    //P0.4 管脚
//        GPIO_InitStructure.Mode = GPIO_OUT_PP;                        //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
//        GPIO_Inilize(GPIO_P0,&GPIO_InitStructure);                //
        // LED_BTGpin
//        GPIO_InitStructure.Pin= GPIO_Pin_2;                    //P0.2 管脚
//        GPIO_InitStructure.Mode = GPIO_OUT_PP;                        //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
//        GPIO_Inilize(GPIO_P0,&GPIO_InitStructure);                //
           // LED_BTRpin
        GPIO_InitStructure.Pin= GPIO_Pin_7;                    //P1.7 管脚
        GPIO_InitStructure.Mode = GPIO_OUT_PP;                        //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
        GPIO_Inilize(GPIO_P1,&GPIO_InitStructure);                //
        //SYS_LED
        GPIO_InitStructure.Pin= GPIO_Pin_0;                    //P5.0 管脚
        GPIO_InitStructure.Mode = GPIO_OUT_PP;                        //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
        GPIO_Inilize(GPIO_P5,&GPIO_InitStructure);
   //********************输入****************************
        // Voltage.Solar
        GPIO_InitStructure.Pin= GPIO_Pin_0;                    //P1.0 管脚
        GPIO_InitStructure.Mode = GPIO_HighZ;                        //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
        GPIO_Inilize(GPIO_P1,&GPIO_InitStructure);                //初始化 P1       
       

chess01 发表于 2018-8-20 09:18:07

LM1876 发表于 2018-8-20 09:10
和电路没关系,就是他设置问题

我不认为他设置有问题,请楼主改下电路试一下,记得用新的没用过的单片机,因为没加电阻的电路可能导致单片机内部强上拉mos管烧毁

LM1876 发表于 2018-8-20 09:23:29

chess01 发表于 2018-8-20 09:18
我不认为他设置有问题,请楼主改下电路试一下,记得用新的没用过的单片机,因为没加电阻的电路可能导致单片 ...

不可能,MOS管VGS基本上都有20V以上的耐压,而且还是电容性质。这个单片机电压撑死了也就5V,不可能对MOS管有伤害,就算G极直接接到12V都没事。你那个烧管一定和VGS无关

LM1876 发表于 2018-8-20 09:25:52

chess01 发表于 2018-8-20 09:18
我不认为他设置有问题,请楼主改下电路试一下,记得用新的没用过的单片机,因为没加电阻的电路可能导致单片 ...

你那个烧管静电击穿的可能性最大。再就是MOS管带的负载有短路

Codoox 发表于 2018-8-20 09:27:12

chess01 发表于 2018-8-20 09:18
我不认为他设置有问题,请楼主改下电路试一下,记得用新的没用过的单片机,因为没加电阻的电路可能导致单片 ...

如果是NPN管确实要串电阻,我现在是驱动NMOS管。

错误出现在红色部分,P46错配成P42了

        P4M1 &= ~0x04;         // P42
        P4M0 |=0x04;
        P4M1 &= ~0x02;         // P41
        P4M0 |=0x02;
        P3M1 &= ~0x20;         // P35
        P3M0 |=0x20;
       
        P4M1 &= ~0x08;         // P43I2C
        P4M0 &= ~0x08;
        P4M1 &= ~0x04;         // P46I2C
        P4M0 &= ~0x04;

chess01 发表于 2018-8-20 09:41:28

LM1876 发表于 2018-8-20 09:25
你那个烧管静电击穿的可能性最大。再就是MOS管带的负载有短路

我说的烧管是单片机内部的管,这个管最大持续电流是20mA,瞬间电流不详.

MOS管的GS间是存在一个结电容的,这个电容被充满电之前,GS近乎短路,P42输出高电平的瞬间,这个电流多大未知,有没有超过单片机的最大允许电流也未知,让电路工作在未知状态是不严谨的,哪怕只是一瞬间

Codoox 发表于 2018-8-20 09:59:46

chess01 发表于 2018-8-20 09:41
我说的烧管是单片机内部的管,这个管最大持续电流是20mA,瞬间电流不详.

MOS管的GS间是存在一个结电容的, ...

这个结电容是非常小的一般都是pF级别的,信号线上用102的滤波电容都不会出问题,这么小的结电容我认为问题不大

1826772880 发表于 2018-8-25 21:21:21

LM1876 发表于 2018-8-20 09:15
#include        "STC15_GPIO.h"
unsigned char GPIO_Inilize(unsigned char GPIO, GPIO_InitTypeDef *GPIOx)
{


这操作,厉害了,指针都用上了

XTXB 发表于 2018-9-1 09:56:28


页: [1]
查看完整版本: STC15F2K60S2 P42管脚驱动能力弱问题