在STM32定义结构体数组的过程中,我发现将结构体数组的位置定义在不一样的位置会有不一样的结果。结构梯定义的是按键的功能,当短按下按键后实现LCD屏幕界面切换。目前的问题是定义的key[0]按键的使用不正常,然而同样操作的key[1]、]key[2]、key[3]
功能正常。下图是问题所在:
下面是有问题的代码定义
__IO uint32_t uwadc;
__IO uint32_t uwuart;
__IO uint32_t uwled,uwled2,uwled3;
unsigned char led_time2,led_time3;
char lcd_string[30];
float V;
float H;
int H1=10,H2=20,H3=30;
unsigned char menu=0;
unsigned char level,level_old;
typedef struct
{
unsigned char judge_sta;
unsigned char key_sta;
unsigned char single_flag;
}keys;
keys key[4];
unsigned char uart_len;
unsigned char uart_word;
char uart_string[30];
unsigned char Threshold=1;
后来我发现将keys key[4];放置在其他位置则key[0]的功能正常。
typedef struct
char unsicned judgesta;
har unsigned keysta;
unsigned char single flag
L)keys; 正常
keys key[4];
IO uint32t uwadc
IOuint32t uwuart
IOuint32t uwled,uwled2,uwled3;
unsicned char ledtime2,ledtime3
char lcd string[30】
floatV
float H
intH1=10,H2=20,H3=30;
unsicned char menu=0
unsigned char level,level old;
unsigned char uart len
unsigned char uart word:
charuart string[30];
unsigned char Threshold=l
这是可以正常运行的代码;
__IO uint32_t uwadc;
__IO uint32_t uwuart;
__IO uint32_t uwled,uwled2,uwled3;
unsigned char led_time2,led_time3;
char lcd_string[30];
float V;
float H;
int H1=10,H2=20,H3=30;
unsigned char menu=0;
unsigned char level,level_old;
typedef struct
{
unsigned char judge_sta;
unsigned char key_sta;
unsigned char single_flag;
}keys;
unsigned char uart_len;
unsigned char uart_word;
char uart_string[30];
unsigned char Threshold=1;
keys key[4];
请问我的问题出在哪里呢?是软件问题还是硬件问题呢?
#include "main.h"
#include "stdio.h"
#include "i2c.h"
#include "string.h"
ADC_HandleTypeDef hadc2;
TIM_HandleTypeDef htim4;
UART_HandleTypeDef huart1;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_ADC2_Init(void);
static void MX_TIM4_Init(void);
static void MX_USART1_UART_Init(void);
//用户代码区
__IO uint32_t uwadc;
__IO uint32_t uwuart;
__IO uint32_t uwled,uwled2,uwled3;
unsigned char led_time2,led_time3;
char lcd_string[30];
float V;
float H;
int H1=10,H2=20,H3=30;
unsigned char menu=0;
unsigned char level,level_old;
typedef struct
{
unsigned char judge_sta;
unsigned char key_sta;
unsigned char single_flag;
}keys;
unsigned char uart_len;
unsigned char uart_word;
char uart_string[30];
unsigned char Threshold=1;
keys key[4];
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM4)
{
key[0].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
key[1].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
key[2].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
key[3].key_sta=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
for(int i=0;i<4;i++)
{
switch(key[i].judge_sta)
{
case 0:
{
if(key[i].key_sta==0)
{
key[i].judge_sta=1;
}
else
{
key[i].judge_sta=0;
}
}
break;
case 1:
{
if(key[i].key_sta==0)
{
key[i].judge_sta=2;
key[i].single_flag=1;
}
else
{
key[i].judge_sta=0;
}
}
break;
case 2:
{
if(key[i].key_sta==1)
{
key[i].judge_sta=0;
}
}
break;
}
}
}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart==&huart1)
{
uart_string[uart_len]=uart_word;
uart_len++;
HAL_UART_Receive_IT(&huart1,&uart_word,1);
}
}
unsigned char i2c_read(unsigned char address)
{
I2CStart();
I2CSendByte(0XA0);
I2CWaitAck();
I2CSendByte(address);
I2CWaitAck();
I2CStart();
I2CSendByte(0XA1);
I2CWaitAck();
unsigned char val=I2CReceiveByte();
I2CWaitAck();
I2CStop();
return val;
}
void i2c_write(unsigned char address,unsigned char info)
{
I2CStart();
I2CSendByte(0XA0);
I2CWaitAck();
I2CSendByte(address);
I2CWaitAck();
I2CSendByte(info);
I2CWaitAck();
I2CStop();
}
void adc_proc()
{
if(uwTick-uwadc>=1000)
{
uwadc=uwTick;
HAL_ADC_Start(&hadc2);
V=HAL_ADC_GetValue(&hadc2)*3.3/4096;
H=V*100/3.3;
if(H<=H1)level=0;
if(H<=H2&&H>H1)level=1;
if(H>H2&&H<=H3)level=2;
if(H>H3)level=3;
}
}
void lcd_proc()
{
if(menu==0)
{
sprintf(lcd_string," Liquid Level ");
LCD_DisplayStringLine(Line2,(unsigned char*)lcd_string);
sprintf(lcd_string," Height:%.0fcm ",H);
LCD_DisplayStringLine(Line4,(unsigned char*)lcd_string);
sprintf(lcd_string," ADC:%.2fV ",V);
LCD_DisplayStringLine(Line5,(unsigned char*)lcd_string);
sprintf(lcd_string," Level:%d ",level);
LCD_DisplayStringLine(Line6,(unsigned char*)lcd_string);
}
if(menu==1)
{
if(Threshold==1)
{
sprintf(lcd_string," Parameter Setup ");
LCD_DisplayStringLine(Line2,(unsigned char*)lcd_string);
LCD_SetTextColor(Green);
sprintf(lcd_string," Threshold 1:%dcm ",H1);
LCD_DisplayStringLine(Line4,(unsigned char*)lcd_string);
LCD_SetTextColor(White);
sprintf(lcd_string," Threshold 2:%dcm ",H2);
LCD_DisplayStringLine(Line5,(unsigned char*)lcd_string);
sprintf(lcd_string," Threshold 3:%dcm ",H3);
LCD_DisplayStringLine(Line6,(unsigned char*)lcd_string);
}
else if(Threshold==2)
{
sprintf(lcd_string," Parameter Setup ");
LCD_DisplayStringLine(Line2,(unsigned char*)lcd_string);
sprintf(lcd_string," Threshold 1:%dcm ",H1);
LCD_DisplayStringLine(Line4,(unsigned char*)lcd_string);
LCD_SetTextColor(Green);
sprintf(lcd_string," Threshold 2:%dcm ",H2);
LCD_DisplayStringLine(Line5,(unsigned char*)lcd_string);
LCD_SetTextColor(White);
sprintf(lcd_string," Threshold 3:%dcm ",H3);
LCD_DisplayStringLine(Line6,(unsigned char*)lcd_string);
}
else if(Threshold==3)
{
sprintf(lcd_string," Parameter Setup ");
LCD_DisplayStringLine(Line2,(unsigned char*)lcd_string);
sprintf(lcd_string," Threshold 1:%dcm ",H1);
LCD_DisplayStringLine(Line4,(unsigned char*)lcd_string);
sprintf(lcd_string," Threshold 2:%dcm ",H2);
LCD_DisplayStringLine(Line5,(unsigned char*)lcd_string);
LCD_SetTextColor(Green);
sprintf(lcd_string," Threshold 3:%dcm ",H3);
LCD_DisplayStringLine(Line6,(unsigned char*)lcd_string);
LCD_SetTextColor(White);
}
}
}
unsigned char t;
void key_proc()
{
if(key[0].single_flag==1)
{
if(menu==0)
{
menu=1;
}
else
{
menu=0;
Threshold=1;
i2c_write(0,H1);
HAL_Delay(10);
i2c_write(1,H2);
HAL_Delay(10);
i2c_write(2,H3);
HAL_Delay(10);
}
key[0].single_flag=0;
}
if(key[1].single_flag==1&&menu==1)
{
Threshold++;
if(Threshold>3)
{
Threshold=1;
}
key[1].single_flag=0;
}
if(key[2].single_flag==1&&menu==1)
{
if(Threshold==1)
{
H1=H1+5;
if(H1>95)
{
H1=95;
}
}
if(Threshold==2)
{
H2=H2+5;
if(H2>95)
{
H2=95;
}
}
if(Threshold==3)
{
H3=H3+5;
if(H3>95)
{
H3=95;
}
}
key[2].single_flag=0;
}
if(key[3].single_flag==1&&menu==1)
{
if(Threshold==1)
{
H1=H1-5;
if(H1<=0)
{
H1=0;
}
}
if(Threshold==2)
{
H2=H2-5;
if(H2<=0)
{
H2=0;
}
}
if(Threshold==3)
{
H3=H3-5;
if(H3<=0)
{
H3=0;
}
}
key[3].single_flag=0;
}
}
unsigned char judge_uart()
{
if(uart_len==1)
{
if(uart_string[0]=='C')return 1;
else if(uart_string[0]=='S')return 2;
else HAL_UART_Transmit(&huart1,"ERROR\n",6,1000);
}
else
{
return 0;
}
}
void uart_proc()
{
if(uwTick-uwuart<=100)return;
uwuart=uwTick;
if(judge_uart()==1)
{
char text[30];
sprintf(text,"C:H%0.0f+L%d\r\n",H,level);
HAL_UART_Transmit(&huart1,text,strlen(text),1000);
led_time3=1;
}
if(judge_uart()==2)
{
char text[30];
sprintf(text,"S:TL%d+TM%d+TH%d\r\n",H1,H2,H3);
HAL_UART_Transmit(&huart1,text,strlen(text),1000);
led_time3=1;
}
uart_len=0;
}
void uart_output()
{
if(level1;
level_old=level;
char text[30];
sprintf(text,"A:H%0.0f+L%d+D\r\n",H,level);
HAL_UART_Transmit(&huart1,text,strlen(text),1000);
}
else if(level>level_old)
{
led_time2=1;
level_old=level;
char text[30];
sprintf(text,"A:H%0.0f+L%d+U\r\n",H,level);
HAL_UART_Transmit(&huart1,text,strlen(text),1000);
}
}
void led_proc()
{
if(uwTick-uwled>=1000)
{
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_8);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,1);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,0);
uwled=uwTick;
}
if(uwTick-uwled2>=200&&led_time2>0)
{
uwled2=uwTick;
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_9);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,1);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,0);
led_time2++;
if(led_time2>10)
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_9,1);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,1);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,0);
led_time2=0;
}
}
if(uwTick-uwled3>=200&&led_time3>0)
{
uwled3=uwTick;
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_10);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,1);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,0);
led_time3++;
if(led_time3>10)
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_10,1);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,1);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,0);
led_time3=0;
}
}
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_ADC2_Init();
MX_TIM4_Init();
MX_USART1_UART_Init();
LCD_Init();
LCD_Clear(Black);
LCD_SetBackColor(Black);
LCD_SetTextColor(White);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,1);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,1);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,0);
level=level_old;
// i2c_write(0,30);
// HAL_Delay(10);
//
// i2c_write(1,50);
// HAL_Delay(10);
//
// i2c_write(2,70);
// HAL_Delay(10);
H1=i2c_read(0);
HAL_Delay(10);
H2=i2c_read(1);
HAL_Delay(10);
H3=i2c_read(2);
HAL_Delay(10);
HAL_UART_Receive_IT(&huart1,&uart_word,1);
HAL_TIM_Base_Start_IT(&htim4);
while (1)
{
adc_proc();
lcd_proc();
key_proc();
uart_proc();
uart_output();
led_proc();
}
}
你这是典型的越界访问踩内存问题。
比如
int a;
int b[3];
int c;
如果你代码中修改了b[-1]或b[3],a或者c的值就会被修改。
我记得本栏的第三篇和第四篇博文的设计中大量使用了库函数和别人的开源代码,鲁迅先生的“拿来主义”表现的淋漓尽致,这也是STM32库函数开发的魅力所在,为了展示结合网络资源和各种资源呈现一个曾经热门的设计,所以诞生第五篇博文。
这次的方案主要是:最简单的单片机摄像头颜色跟踪方案。下面请看全家福:
优酷视频演示地址:https://v.youku.com/v_show/id_XNTEzOTQxMTA5Mg==.html
直接观看
正点原子探索者开发板摄像头颜色跟踪
这个方案历史的起源是2012年阿莫论坛一个博主发布了一个颜色跟踪的代码,链接是:https://www.amobbs.com/thread-5499408-1-1.html
截图如下(铭记历史):
差不多国内的所有基于单片机的颜色识别方案都用了这个内容,包括电路城里面很多卖家的电路。这个曾经火热的开源代码网站逐步走向了没落,这个网站现在有些服务好像是要花钱的了,取而代之的是正点原子开源论坛和野火开源论坛,这些论坛真的开源力度够,我也不是他们的托,事实说话。为了学习ESP8266,我曾经把正点原子关于ESP8266的帖子全部看完了,呵呵,有意思。这个颜色开源的代码也被拿来作为买卖商品,不过这也是无可厚非,想把这套代码在固定的硬件跑起来确实要花费不少功夫的,正点原子赠送的源码是没有F407驱动OV7725摄像头的,只有F1驱动OV7670的代码,我从F103的OV7670移植过去成为现在的F407驱动OV7725,正点原子配套的F407手册也只有OV2640摄像头的教程而已,OV2640摄像头没有FIFO意义不大,OV7725的性能要比OV7670的要好,所以我全选最好的。我使用的硬件平台是正点原子全家桶:探索者F407开发板,OV7725摄像头模块,ALIENTEK 4.3 TFTLCD,全部模块都是插上就用,原理图都是用的他们家的省事省力,这就是项目开头所说的:“注释最详细、代码最简单”的效果了,高校的学生只要有这个开发板,买了我的方案保证能快速掌握颜色跟踪,我的代码绝对让你物有所值。