1、原理图
2、代码
(1)底层寄存器IO口定义
IO1,2,3代表的是IO口的输出为1还是0。
IO1,2,3C代表的是控制IO口的输入(1)还是输出(0)模式。
IO1,2,3PU代表的是IO口的上拉使能(1)还是禁用(0)。
(2)将IO口的操作进行函数封装
看原理图知道要想LED1亮,首先要让IO1和IO2为输出模式,IO3为输入模式,之后在让IO1和IO2分别输出高电平和低电平。
主函数里面首先我要注释掉中断里面的led扫描函数,然后先尝试单独点灯是否能亮,在所有的灯都能单独点亮的情况下,在尝试组合亮,全亮。
(3) 问题
当单独点亮led1的时候,D1和D6同时亮了
当单独点亮led2的时候,D2和D4同时亮了
(4)问题分析
通过看原理图,我们可以知道D6亮时IO3高,IO2低,D1亮是IO1高,IO2低。
D4亮是IO3高,IO1低,D2亮是IO2高,IO1低。
综上分析就是不知道我的哪个配置出现错误,导致IO3也就是pa6引脚输出了高电平。
因此我需要找到关于pa6的配置
(5)问题已解决
问题出在我的IO初始化函数里面
一开始我将所有的pa口都设置为输入模式,然后pa都是低电平,但是在看到pa所有引脚的上拉初始化的时候,我发现我把pa6设置为输入上拉,也就是pa6的空闲状态是高电平。
因此我只需要将_papu = 0B00000000,这样就能实现单独点灯了。
1、原理图
2、问题现象
单独点亮LED1,亮LED1,LED2微亮
单独点亮LED2和3,都能单独亮
单独点亮LED4,亮LED4,LED3微亮
3、接下来要做的事情
(1)根据原理图检查代码的底层配置对不对
原理图上:IO1:PB3 IO2:PB1 IO3:PA6
a、IO口配置代码:
// output
#define IO1 _pb3
#define IO2 _pb1
#define IO3 _pa6
// input(1)/output(0)
#define IO1C _pbc3
#define IO2C _pbc1
#define IO3C _pac6
// pull up enable(1)/disable(0)
#define IO1PU _pbpu3
#define IO2PU _pbpu1
#define IO3PU _papu6
b、IO初始化代码:
PA所有引脚全部设置为输入模式,下拉
PB3、4、5设置为输入模式,其中PB3是IO1,PB4为按键,PB5是HS,其中PB4设置为输入上拉
_pac = 0B11111111; //1:input 0:output
_papu = 0B00000000;
_pa = 0x00;
_pbc = 0B00111000; //1:input 0:output
_pb = 0x00;
_pbpu = 0B00010000;
(2)根据原理图检查外部实现
a、外部实现代码
LED1亮,IO1和IO2设置为输出模式(注意IO1初始化为输入模式,这里修改了),IO3设置为输入模式,同时IO1输出高电平,IO2输出低电平。
下面根据原理图依次类推LED2 、LED3、 LED4。
void LED1_light(void)
{
#if LED_DISPLAY_EN
IO1C = 0;
IO2C = 0;
IO3C = 1;
IO1 = 1;
IO2 = 0;
#endif
}
void LED2_light(void)
{
#if LED_DISPLAY_EN
IO1C = 0;
IO2C = 0;
IO3C = 1;
IO1 = 0;
IO2 = 1;
#endif
}
void LED3_light(void)
{
#if LED_DISPLAY_EN
IO1C = 1;
IO2C = 0;
IO3C = 0;
IO2 = 1;
IO3 = 0;
#endif
}
void LED4_light(void)
{
#if LED_DISPLAY_EN
IO1C = 1;
IO2C = 0;
IO3C = 0;
IO3 = 1;
IO2 = 0;
#endif
}
b、补充(找到原因了)
至此,我在主函数依次调用LED1_Light(),LED2_Light(),LED3_Light(),LED4_Light()
效果是 1亮2微亮; 2亮; 3亮; 4亮,3微亮;
当我注释掉中断函数里面的fun_led_scan()函数时,档位灯都能正常亮。说明我的底层调用以及配置是正确的。
因此我认为问题出在以下的灯光扫描函数里面。
void fun_LED_scan(void)
{
static unsigned char ledIndex = 0;
ledIndex ++;
if(ledIndex >= 6) //因为只有四个灯,所以我删去了了两个灯,等于4
ledIndex = 0; //事实上等于4也是错误的,因为index = 0,++以后为1
//所以根本进不了case0。
LEDall_OFF();
switch(ledIndex)
{
case 0:
if(bLED1)
LED1_light(); //要想从case0开始,我们需要把++放到case中
eg:ledIndex ++;
break;
case 1:
if(bLED2)
LED2_light();
eg:ledIndex ++;
break;
case 2:
if(bLED3)
LED3_light();
eg:ledIndex ++;
break;
case 3:
if(bLED4)
LED4_light();
eg:ledIndex = 0;
break;
case 4:
if(bLED5)
LED5_light(); //去掉
break;
case 5:
if(bLED6)
LED6_light(); //去掉
break;
default :
LEDall_OFF();
ledIndex = 0;
break;
}
}
c、总结
这次的原因不在于底层IO口的配置,但是我花费了大量时间在这上面,因此我再次总结以下顺序
灯光调试:
1、底层配置:.h文件中的IO口,.c文件中IO_init里面的初始化
2、外部实现:led扫描的函数逻辑,重复的IO口复用(全局搜索IO口)
3、单独点亮调试:需要加清理看门狗GCC_CLRWDT();,需要加时基单元if(timebase == 1) timebase = 0;