蓝桥杯嵌入式代码查找心得

本人参加了第九届蓝桥杯嵌入式国赛,最后成绩国赛二等奖,差几名的样子就能拿一等奖的水平(比赛成绩排名在名单第一页,大概十几到二十来名?没去仔细数。。)

下面是在蓝桥杯准备期间的一些心得和快速代码查找的方法和注意事项,特地分享出来,供大家参考。希望能够帮助到大家。

鉴于能力水平有限,也知道蓝桥杯嵌入式组的含金量比较低,请大牛们勿喷。

欢迎分享转发,但请注明出处。谢谢各位大佬。                                                              ——Arthur

LCD :

LCD的参考例程,同时里面还有SYStick的使用,记得中断里面systick的中断函数,还有lcd.c里面 延时函数的修改。但是不要删掉与原来的#include<stdio.h>

另外关于sprintf的使用方式:

sprintf((char *)str," Threshold 1: %dcm        ",low);

LCD_DisplayStringLine(Line3,str);

其中str的定义是 u8 str[20];千万不要在u8 str[] 这样的定义后面放乱七八遭的东西,肯定会干扰str,从而输出一些乱七八糟的东西。所以最好要定义为u8 str[20];

LED :

 GPIO -- JTAG_Remap --main 。还有库函数头文件里面的set和reset调用

同时需要创建一个LED.h 来定义LED0~LED8和LEDALL。还要写led_turn和led_off俩个函数。而且在对led进行操作时,需要在外围加上:GPIOC->ODR = ReadLED和 ReadLED = GPIOC->ODR (注意先后顺序)以保证各led之间不会造成相互干扰。关于LED的控制可以直接写在SYStick的中断函数里面。对中断的时间影响也不是很大。千万别复制错RB1_4的宏定义函数。

KEY : led.h里面定义RB1到RB4,然后在Gpio.init里面添加关于KEy的GPIO初始化(初始化可以不写的)。然后在写key_scan()的按键扫描函数。该函数中记得要先写while循环检测按键松开,再返回return,不然while会失效。还要再写一个KEY_check()函数,这是为了方便最后的EEPROM的操作对按键延时的动态性干扰。按键的GPIO可以不初始化,因为默认就有浮空输入了,别被之前的LED初始化干扰了GPIO设置。并且按键按下的时候,按键的值是0;注意看原理图。

 

以上就是半小时的东西。

 

接下来就是其他各种见证奇迹的时刻

ADC :ADC -- AnalogWatchdog -- main里面删除有关于analogwatchdog的东西(一共四句,包括一个中断),并且将ADC1的通道从14改为8.

至于ADC的时钟源分频好像差别不是很大。需要之后查PCLK2的时钟再说。要保证ADC的时钟源ADCCLK不超过14MHz。理论上得是6分频。(systemInit中设置了PCLK2为72MHz,除了APB1为36MHz以外,另外初始值都是72MHz)。

初始化PB0口GPIO,这个是ADC1 通道8。。记得开启ADC的时钟,都可以找到的,别漏了.

ADC_SoftwareStartConvCmd(ADC1,ENABLE)来进行采集ADC的数据

然后在adc的库函数头文件里面找到ADC_GetConversionValue(ADC1)来进行ADC采集函数AD_Read()。

最后注意 ADC_VALUE = ADC_GetConversionValue(ADC1)*3.3/0xfff;//别忘了这个公式!!0xfff!!因为满电压的值是0xfff.

sprintf((char *)string, "ADC: %.2fV       ",ADC_VALUE); //其中u8 string[20];

LCD_DisplayStringLine(Line3,string);

最后别忘了ADC_value的定义要是float,因为电压是一个小数啊!!

I2C :

先把i2c.h和i2c.c加入到工程中去。然后打开i2c.h,开始写void IIC_Write(unsigned char add,unsigned char dat)和unsigned char IIC_Read(unsigned char add);(实在忘记了怎么写的话,可以打开EEPROM的数据手册,查看random read和 byte write的时序图,写操作是0xa0,读操作是0xa1)

同时别忘了要调用i2c_init()来初始化i2c,在头文件中也要包含i2c.h。接着就可以来操作EEPROM。每次使用IIC_Write和IIC_Read完的时候,都要进行5ms的延时。(或者也可以将Delay_Ms(5)的函数写在IIC_Read和IIC_Write俩个函数的末尾处)。写0x20可能会出现板子的EEPROM被人使用相同方法写过导致不能够初始化的情况,换几个试试。

关于EEPROM的使用:(假设IIC_Read和IIC_Write的尾部已经加上了Delay_Ms(5))

if(IIC_Read(0x20) != 20)

{

IIC_Write(0x00,30);

IIC_Write(0x01,50);

IIC_Write(0x02,70);

IIC_Write(0x20,20);

}

 

low = IIC_Read(0x00);

mid = IIC_Read(0x01);

high = IIC_Read(0x02);

(这样就可以将上次的保存的值读出来了)

 

 

USART:

USART --  interrupt --找到USART的初始化以及USART2的时钟使能,GPIO的初始化,USART的使能以及中断的配置,中断嵌套的初始化也包含其中,我们使用的USART2,对于其中USARTx,y的问题,需要打开同目录下的platform_config进行相关宏定义的查看。其中用的端口是GPIOA的 2(tx)和3 (rx),波特率是9600(这个要看考试要求了)。一般只会用到接收的中断。然后开始写中断处理函数。

串口的初始化的RX TX口要特别注意别搞反了,在库函数中是第二项的宏定义。而且初始化的时钟别看错了,应该是APB1的,在库函数的最下面那个。在中断的时候,为了可以传输字符串,必须在遇到\n的时候关闭中断,处理完字符串之后(比如已经对字符串进行读取和各种判断操作之后,再打开中断。)

在中断服务函数中找到串口的收发程序,然后还要在USART的头文件里面找到USART_ClearITPendingBit,用来清除中断标志位。(其实接收中断标志位不清也没事)

还有就是关于printf的使用,只要重写putchar函数就行,这段代码在USART – printf中就可以找到,记得要打开微库。

RTC :

RTC -- Calendar -- -- 根据LSI_Calib里面的值LSI写法修改RCC_LSEConfig(RCC_LES_ON)成为 RCC_LSICmd(ENABLE),其他的LSE也修改成LSI

修改RTC_SetPrescaler(32767)为39999,因为使用的是LSI时钟。40khz.

其他的时间显示,时间调整,时间获取等函数都在calendar中可以找到。适度修改即可。

并且修改为需要的初始化时钟(在初始化的函数里面加上time_adjust的函数就行)。其中RTC_GetCounter这个函数在库函数中(获得RTC的时间)。

在头文件里面设置初始时钟宏定义,然后复制time_adjust里面的部分代码。

RTC_SetCounter(HH*3600 + MM*60 + SS);

RTC_WaitForLastTask();

其中rtc需要添加的头文件有rtc,bkp,misc,pwr;

最后还要加上RTC的NVIC函数,然后将NVIC的也写到RTC的配置中去,(一般来说NVIC已经在别的地方调用过了,所以看情况)。千万别忘了NVIC!!

库函数中的Time_Display()函数写的不好,会造成没有00:00:00的情况,所以需要这样写  if (RTC_GetCounter() == 0x00015180) //这边加了1

     {

      RTC_SetCounter(0x0);

      RTC_WaitForLastTask();

  TimeVar = RTC_GetCounter(); //这边加上这句,来重新读取以替代原先的TimeVar

    }

最后找到RTC 的中断。别忘了定义和外部定义TimeDisplay这个变量。

然后在主函数里面添加time_Display的函数,进行时间的显示(改写到从LCD中显示)。

TIM PWM :

TIM -- PWM_OutPut  --- 对于定时器的初始化要独立的有一个函数,因为在定时器的初始化过程中,需要有一个参数是占空比的值....TIM2_Configuration()。一定要查清楚到底对应哪一个通道。

另外如果想要使用TIM1进行PWM输出的话,其他的差不多,但是一定要加上TIM_CtrlPWMOutputs(TIM1, ENABLE);这是别的定时器不需要的。

另外TIM_ARRPreloadConfig的设置允许或禁止在定时器工作时向ARR的缓冲器中写入新值,以便在更新事件发生时载入覆盖以前的值。

TIM_OC2PreloadConfig则是输出比较值是否允许在工作时进行修改。所以要DISABLE。

当用到PWM2和USART2的时候,可能会造成引脚之间的冲突。这时候可以考虑采用分时复用。(一般不会发生的,就是PA2口,是USART的RX口,又是TIM2_CH3)

记得时钟一定要使能正确,不然又会没有任何输出了,到底挂在哪个总线下面也是问题。

InputCapture -- 输入捕获 -- 按照所需端口设置 --  复制的内容有TIM还有NVIC还有GPIO  ---  同时还要加上频率,因为官网的输入捕获中没有加上频率(TIMBase的设置)。所以一定要为输入捕获的时钟配置好各种参数。最后还有中断函数。中断函数的书写也可以找到,但是要根据自己设定的输入捕获使用的定时器的值来设定最后定时器频率的计算,比如多除一个72.(除非使用的是全速采集输入捕获:72MHz。另外,定时器周期Period装载值最好是65535à最大),中断中的其他只要把所有相关的都改成本定时器的函数就行。最好就是使用71分频,感觉全速采集就是不准确(不知道为什么)。

输出比较:TIm—OCToggle 对着改就行,注意period必须是65535。而且TIM_OC1PreloadConfig必须关闭。中断函数按照写就行。NVIC什么的都别忘了。中断里面的增加的值可能需要自己计算。

 

 

其他注意事项:

0.第一次删main文件的时候,不要删了#include<stdio.h>,不然sprintf和printf都不能使用。并且记得选上微库的选项。不然printf不能使用。

1.另外关于标志位的书写,如果是用来计数1000ms什么的标志位,一定不要设置为u8,不然永远也不能够成立(计数达不到1000),造成错误。

2.一定要记得需要使用某一个中断的时候,一定要配置相关的NVIC。

3.使用虚拟滤波器的时候的写法是GPIOA_IDR.1 注意是IDR,不要因为使用错误而以为是自己写错了代码!!!

猜你喜欢

转载自blog.csdn.net/Arthur_Holmes/article/details/81192461