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电阻足够了;而且目前是配置成推挽输出,不应该存在驱动能力不够的情况。
这个管脚有什么特殊之处吗?操作的不对? 和别的引脚对比一下;自己加个4K7电阻上拉试试。 检查一下单片机的电源地是否连接正确! 饭桶 发表于 2018-8-19 18:30
检查一下单片机的电源地是否连接正确!
电源地也没有问题,别的功能都正常,目前就发现这个管脚拉不高。现在是把下拉电阻统一换成470K了,能正常工作。
现在不知道是什么原因造成的,怕存在隐患。 虽然STC宣称能提供150uA电流,我还是更相信INTEL的数据,按60UA设计。 不应该是P4M1= 0x00;// P42 输出 红外
P4M0=0x04; 1826772880 发表于 2018-8-19 19:45
不应该是P4M1= 0x00;// P42 输出 红外
P4M0=0x04;
你这样就把P4所有的管脚都设成推挽输出了,上面的代码仅仅是把P42管脚设成推挽 Codoox 发表于 2018-8-19 19:53
你这样就把P4所有的管脚都设成推挽输出了,上面的代码仅仅是把P42管脚设成推挽 ...
你需要冷静看数据手册 su33691 发表于 2018-8-19 19:35
虽然STC宣称能提供150uA电流,我还是更相信INTEL的数据,按60UA设计。
双向口:
手册上写的拉电流270uA,由于制造误差,实际为270uA~150uA。
而且用100K电阻,5V也就才50uA。
推挽输出:
手册写的是可达20mA。 6楼是对的 1826772880 发表于 2018-8-19 19:54
你需要冷静看数据手册
还是没明白,我这样设置有什么错吗? Codoox 发表于 2018-8-19 20:22
还是没明白,我这样设置有什么错吗?
你这个操作是自己研究的还是抄哪里的?先试试我贴的,行的话再继续讨论。 1826772880 发表于 2018-8-19 20:25
你这个操作是自己研究的还是抄哪里的?先试试我贴的,行的话再继续讨论。 ...
按位与,按位或,不都是这么操作的吗?
这样操作有什么错请明示,谢谢!
我翻了一下STC的手册有这样的写法:
P3M1 &=~(1<<4); //P3.4设置为推挽输出
P3M0 |=(1<<4);
上面的1<<4 不应该 = 0x10 吗?
同理第2管脚不应该是 1<<2 = 0x04 吗? Codoox 发表于 2018-8-19 20:41
按位与,按位或,不都是这么操作的吗?
这样操作有什么错请明示,谢谢!
错不错我没精力研究{:lol:},我不明白的是为啥要要运算,而不是直接赋值? 1826772880 发表于 2018-8-19 20:45
错不错我没精力研究,我不明白的是为啥要要运算,而不是直接赋值? ...
直接赋值的话会把别的管脚状态也改掉,按位与或可以保持别的管脚不变,只改变这一个管脚的配置。
这不是很常用的操作方式吗?如果说这种操作方式有错,还是我用的不对,请指正 Codoox 发表于 2018-8-19 20:52
直接赋值的话会把别的管脚状态也改掉,按位与或可以保持别的管脚不变,只改变这一个管脚的配置。
这不是 ...
这样,
1代码问题:
你呢先按照直接赋值试试,可以推挽呢那就是你代码问题,然后呢再请教高手研究下代码哪里有问题。
2芯片问题:
直接赋值不行呢再向STC问芯片问题。
我没对管脚配置用过运算,这个不敢乱说{:lol:}
是不是有别的地方误设置了管脚状态? 1826772880 发表于 2018-8-19 20:45
错不错我没精力研究,我不明白的是为啥要要运算,而不是直接赋值? ...
用表达式运算直观一点,这个没有问题。
运算是由编译器运算的,编译好后的代码和直接赋值的结果是一样的。
好久没玩51了。 你的电路有问题,单片机IO口驱动MOS管应该串一个100欧的电阻,如果因为这个电阻导致关断不够迅速,再在电阻上反并一个二极管 chess01 发表于 2018-8-20 09:04
你的电路有问题,单片机IO口驱动MOS管应该串一个100欧的电阻,如果因为这个电阻导致关断不够迅速,再在电阻上 ...
和电路没关系,就是他设置问题 LM1876 发表于 2018-8-20 09:10
和电路没关系,就是他设置问题
确实是设置问题,后面有个别的管脚错配成P42了 #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
LM1876 发表于 2018-8-20 09:10
和电路没关系,就是他设置问题
我不认为他设置有问题,请楼主改下电路试一下,记得用新的没用过的单片机,因为没加电阻的电路可能导致单片机内部强上拉mos管烧毁 chess01 发表于 2018-8-20 09:18
我不认为他设置有问题,请楼主改下电路试一下,记得用新的没用过的单片机,因为没加电阻的电路可能导致单片 ...
不可能,MOS管VGS基本上都有20V以上的耐压,而且还是电容性质。这个单片机电压撑死了也就5V,不可能对MOS管有伤害,就算G极直接接到12V都没事。你那个烧管一定和VGS无关 chess01 发表于 2018-8-20 09:18
我不认为他设置有问题,请楼主改下电路试一下,记得用新的没用过的单片机,因为没加电阻的电路可能导致单片 ...
你那个烧管静电击穿的可能性最大。再就是MOS管带的负载有短路 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; LM1876 发表于 2018-8-20 09:25
你那个烧管静电击穿的可能性最大。再就是MOS管带的负载有短路
我说的烧管是单片机内部的管,这个管最大持续电流是20mA,瞬间电流不详.
MOS管的GS间是存在一个结电容的,这个电容被充满电之前,GS近乎短路,P42输出高电平的瞬间,这个电流多大未知,有没有超过单片机的最大允许电流也未知,让电路工作在未知状态是不严谨的,哪怕只是一瞬间 chess01 发表于 2018-8-20 09:41
我说的烧管是单片机内部的管,这个管最大持续电流是20mA,瞬间电流不详.
MOS管的GS间是存在一个结电容的, ...
这个结电容是非常小的一般都是pF级别的,信号线上用102的滤波电容都不会出问题,这么小的结电容我认为问题不大 LM1876 发表于 2018-8-20 09:15
#include "STC15_GPIO.h"
unsigned char GPIO_Inilize(unsigned char GPIO, GPIO_InitTypeDef *GPIOx)
{
这操作,厉害了,指针都用上了
页:
[1]