①基于十二届试题
Led引脚要在cubmx中初始化,注意不要忘记PD2控制的锁存器。 为了避免led和lcd引脚冲突,可以封装如下函数:
void LED_disp(unsigned char led_dsp)
{
//熄灭
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC,led_dsp<<8,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
加入让LED1亮则写入(0x01),LED2对应(0x02),LED3对应(0x04),LED4对应(0x08)
LED5(0x10),LED2对应(0x20),LED3对应(0x40),LED4对应(0x80).
注:如果同时想让若干个灯亮,则要进行或运算再写入。
②对于数据的接收是定长数据,我采用的是串口接收空闲中断+DMA。具体使用方法可看我的另一篇文章http://t.csdnimg.cn/6DRbw
数据发送时我采用的是阻塞式发送,如果我们要发送的数据过长,注意将等待时间加长,否则会出现数据发送不全的现象!
char text[18];
sprintf(text,"%s:%s:%d:%.2f",cars[i].car_Leixing,cars[i].car_ID,packing_time,packing_fare);
HAL_UART_Transmit(&huart2,(uint8_t *)text,sizeof(text),50);
③本届试题串口接收数据和对数据的处理是一个重难点。要想方便的处理数据。就不可避免地要会使用一些字符串处理函数。本次使用到的一些如下:
- int atoi (const char * str);其原型定义在stdlib.h头文件中。将数字字符串转换为整数。转换后的值不可超出int可表示的范围。
- Strlen()函数获取字符串长度,从字符首地址开始遍历,以‘\0’为结束标志,计算的长度并不包含‘\0’.. 当字符‘a’,'b','c'三个字符依次存放在arr数组中,并没有储存'\0',而strlen()函数只有遇到‘\0’才会停止,故会返回一个随机值。因此这点我们要注意!!头文件:string.h
- sizeof()是操作符,当参数是一个类型或者变量,返回值为该变量类型的实际大小,比如int型占4个字节,float型占四个字节。sizeof(int)返回值为4.sizeof(2)(因为2是整形)返回值为4表示占四个字节。当参数为一个静态数组,sizeof()返回数组长度。sizeof()不能返回动态数组的长度。sizeof()还可以将函数作为参数。如: short h(); sizeof( h() );返回值为2.
- 【int strcmp(char *str1, char *str2)】,
strcmp比较两个字符串的大小,一个字符一个字符比较,按ASCLL码比较标准规定:
第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字
- 4. strcpy()是覆盖拷贝,
将source全覆盖拷贝到destination,会把’\0’也拷过去,且必须考虑destination的空间够不够
(destination的空间必须>=source的空间)
- 5. strcat()追加拷贝,追加到目标空间后面,目标空间必须足够大,能容纳下源字符串的内容
6.字符串sscanf()函数
int sscanf(const char *str,const char *format,...);
str:需要解析的字符串
format:格式控制字符串
...:可变参数,用于存放解析出来的值
返回值:成功则返回解析的成功数量,失败返回-1
:从一个字符串中提取字符串、浮点数、整数等值,并将其保存到指定的变量中。
例:char str[]="123 4.56 hello";
int x; float y; char z[20];
sscanf(str,"%d %f %s",&x,&y,z);
得:x=123 y=4.560000 z=‘hello’
7、sprintf()函数:和printf用法几乎一样,只不过打印地点不同。前者打印到字符串中,后者在命令行上输出。
sprintf(s,"%d",123) //把整数123打印成一个字符串保存在s中
sprintf(s,"%8d",123) //指定宽度,不足左边补空格(右对齐)
sprintf(s,"%-8d",123) //指定宽度,左对齐
sprintf(s,"%x",123) //把整数123以十六进制保存在s中
sprintf(s,"%04x",123) //把整数123以十六进制保存在s中,左边补0等宽为4的模式
sprintf(s,"%f",0.123) //把浮点数打印成一个字符串保存在s中,默认六位小数
sprintf(s,"%2.3f",0.123) // "m.nf"表示:宽度为m,保留n位小数
④对于停车时间的计算,我只能进行粗略的计算。希望如果有人会的话分享在评论区。
⑤对于汽车的信息有很多,我采用了结构体进行保存。关于结构体我有如下收获:
1、结构体可以直接进行赋值:
struct Point {
int x;
int y;
};
int main() {
Point p1 = {1, 2};
Point p2;
// 直接赋值
p2 = p1;
// 现在p2的成员等于p1的成员
// 所以p2.x == 1, p2.y == 2
return 0;
}
2、当车出库时,不要忘记将该车之后的车往前提,以保证链接。同时防止结构体数组越界,如下操作
//出停车厂后,要保证结构体数组的连贯性,将i后面的信息向前移一个
uint8_t t;
for(t=i;t<7;t++) //不要越界
{
cars[t]=cars[t+1];
}
//同时保证车辆--,停车厂总数量--
if((strcmp(Leixing , "CNBR")==0))
{
CNBR_num--;
IDLE_num++;
}
if(strcmp( Leixing ,"VNBR")==0)
{
VNBR_num--;
IDLE_num++;
}
3、结构体的初始化
参考该文章http://t.csdnimg.cn/8vMkL
假设我们有
struct Student
{
long id;
char name[20];
char sex;
}
struct Student a={0};
其相当于a.id=0;a.name=“”;a.sex=‘/0x0’。
仅仅对其中部分的成员变量进行初始化,要求初始化的数据至少有一个,其他没有初始化的成员变量由系统完成初始化,为其提供缺省的初始化值。各种基本数据类型的成员变量初始化缺省值如表
数据类型
缺省初始化值
Int 0
Char ‘/0x0’
float 0.0
double 0.0
char Array[n] ”
int Array[n] {0,0…,0}
⑥判断一个字符是否为数字的两种方法(C/C++)
直接判断“
#include <stdio.h>
int main()
{
char c;
c = getchar();//读取一个字符。
if(c >='0' && c<='9')printf("是数字\n");
else if(c >='a' && c<='z' || c >='A' && c<='Z'))
printf("是字母\n");
else
printf("是特殊字符\n");
return 0;
}
库函数法
int main()
{
char c;
c = getchar();
//来判断是否为数字,如果是数字那么会返回非0
if(isdigit(c) != 0)
printf("是数字\n") ;
//来判断是否为字母,如果是字母那么返回非0
else if(isalpha(c) != 0)
printf("是字母\n");
else
printf("是特殊字符\n");
}
十三届国赛心得:
字符串处理还是不精,老是忘记他们的作用,
还有常给我焊的板子ad不准调了两天最后发现是一个保险丝没焊。
lcd翻转显示不会
⑦串口接收初始化
//串口配置
__HAL_UART_CLEAR_IDLEFLAG(&huart2);//防止一上电就进中断!!!!
__HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE);
HAL_UART_Receive_DMA(&huart2,Rx_buf,Buf_long);
犯的错误:1、我用定时器2输出pwm时 占空比初始设置为了0,我用定时器三输入捕获总是读值CCR总是为0,最后发现我输出的pwm占空比为0就没有高低电平的改变,输入捕获时检测不到上升沿下降沿故读值总为0。
2、忽略了时序的问题,简单的几句话也封装函数造成了工程的冗余,蓝桥杯属于小工程比赛,我们可以直接将逻辑实现在while中。保证了时序的正确性,也避免了冗余,好修正错误。
3、eeprom的写入需要时间,故要加延时保证数据写入正确。而数据的读出一般不用加。且封装eeprom的读写函数时,当我们要指定地址读出一个字节时,最后应该给出I2CSendNotAck();
//eeprom 写入一个字节
void Write_onebyte(uint8_t ADDRESS,uint8_t byte)
{
I2CStart();
I2CSendByte(0xA0);
I2CWaitAck();
I2CSendByte(ADDRESS);
I2CWaitAck();
I2CSendByte(byte);
I2CWaitAck();
I2CStop();
}
void Read_onebyte(uint8_t ADDRESS,uint8_t *byte)
{
I2CStart();
I2CSendByte(0xA0);
I2CWaitAck();
I2CSendByte(ADDRESS);
I2CWaitAck();
//I2CStop(); //可写可不写
I2CStart();
I2CSendByte(0xA1);
I2CWaitAck();
*byte = I2CReceiveByte();
I2CSendNotAck(); //一定要发送的是不应答
I2CStop();
}
4、单adc多通道采集时,要记得等待转换完成才能进行下一个通道的采集,否则会出现数据不准确情况。
5、别忘记输入捕获初始化函数如下:
HAL_TIM_IC_Start(&htim2,TIM_CHANNEL_2);
我采用的主从触发模式,当采集到波形的一个周期的上升沿来临时CNT++,当下降沿来临时将CNT的值保存到CCR中,并且复位CNT的值,直到下一个周期的上升沿来临重复上次操作。获得捕获到的CCR的函数为
Temp= HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_2);
6、当我们要判断接收的数据是什么时,可以采用如下方法:首先将数据强制转换为字符串,然后运用strcmp()比较字符串是否相等;
if(__HAL_UART_GET_FLAG(&huart2,UART_FLAG_IDLE)==SET)
{
__HAL_UART_CLEAR_IDLEFLAG(&huart2);//清除空闲中断标志位
HAL_UART_DMAStop(&huart2);
sprintf(Rx_temp,"%s",Rx_buf); //将接收到的数字数据转为字符串(强制类型转换)
if(strcmp(Rx_temp,"X")==0) //比较接收到的字符串是否为‘X’
{
char str[20]; //有符号八位字符(-128-127)
sprintf(str,"Fre_para = %d\r\n",Fre_para);
HAL_UART_Transmit(&huart2,(uint8_t *)str,strlen(str),20);
}
//计算接收数据长度
// Rceive_long = Buf_long-__HAL_DMA_GET_COUNTER(&hdma_usart2_rx);
// HAL_UART_Transmit(&huart2,Rx_buf,Rceive_long,20);
//重新开启串口接收
HAL_UART_Receive_DMA(&huart2,Rx_buf,Buf_long);
}
后续还有总结,我会继续更的。如果有错误请指正呢