BSP模块训练题详解及解析
1.串口1收发
本题需要使用串口1与PC机进行通信。定义串口1数据的接收区与发送区,数据包匹配头部。初始化串口波特率为2400,设置串口的接收区和数据包头。设置回调函数,若串口1接收到数据包,则将接收到的数据倒序发送回计算机。
#include "STC15F2K60S2.H" //必须。
#include "sys.H" //必须。
#include "uart1.h"
code unsigned long SysClock=11059200; //必须。定义系统工作时钟频率(Hz),用户必须修改成与实际工作频率(下载时选择的)一致
#ifdef _displayer_H_ //显示模块选用时必须。(数码管显示译码表,用戶可修改、增加等)
code char decode_table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x08,0x40,0x01,0x41,0x48,0x76,0x38,0x40,0x00,
/* 序号: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 */
/* 显示: 0 1 2 3 4 5 6 7 8 9 (无) 下- 中- 上- 上中- 中下- H L - (无)*/
0x3f|0x80,0x06|0x80,0x5b|0x80,0x4f|0x80,0x66|0x80,0x6d|0x80,0x7d|0x80,0x07|0x80,0x7f|0x80,0x6f|0x80 };
/* 带小数点 20 21 22 23 24 25 26 27 28 29 */
#endif
char rxd[10];
char buffer[10];
char matchhead[2]={0xaa,0x55};
void uart1rxd_callback();
void main()
{
//串口初始化
Uart1Init(2400);
SetUart1Rxd(rxd, 10, matchhead, 2);
SetEventCallBack(enumEventUart1Rxd, uart1rxd_callback);
MySTC_Init();
while(1)
{
MySTC_OS();
}
}
void uart1rxd_callback(){
int i;
for(i=9;i>=0;i--){
buffer[i] = rxd[9-i];
}
Uart1Print(buffer, 10);
return;
}
2.串口2通信
两板使用RS485作为串口2进行通信,使用按键模块控制发送,显示模块将结果显示在LED。对串口2设置5字节的数据接收区和2字节的数据包头,波特率为1200。设置两个回调函数,按下Key1则通过串口2发送定义好的数据,串口2若接收到数据包则将数据求累加和通过led显示。
#include "STC15F2K60S2.H" //必须。
#include "sys.H" //必须。
#include "displayer.h"
#include "key.h"
#include "Uart2.h"
code unsigned long SysClock=11059200; //必须。定义系统工作时钟频率(Hz),用户必须修改成与实际工作频率(下载时选择的)一致
#ifdef _displayer_H_ //显示模块选用时必须。(数码管显示译码表,用戶可修改、增加等)
code char decode_table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x08,0x40,0x01,0x41,0x48,0x76,0x38,0x40,0x00,
/* 序号: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 */
/* 显示: 0 1 2 3 4 5 6 7 8 9 (无) 下- 中- 上- 上中- 中下- H L - (无)*/
0x3f|0x80,0x06|0x80,0x5b|0x80,0x4f|0x80,0x66|0x80,0x6d|0x80,0x7d|0x80,0x07|0x80,0x7f|0x80,0x6f|0x80 };
/* 带小数点 20 21 22 23 24 25 26 27 28 29 */
#endif
unsigned char rxd[5];
unsigned char buffer[5] = {0xaa,0x55,0x01,0x01,0x01};
unsigned char matchhead[2]={0xaa,0x55};
void uart2rxd_callback();
void key_callback();
void main()
{
//初始化
KeyInit();
DisplayerInit();
SetDisplayerArea(0,7);
Seg7Print(10,10,10,10,10,10,10,10);
Uart2Init(1200,Uart2Usedfor485);
SetUart2Rxd(rxd, 5, matchhead, 2);
//设置回调
SetEventCallBack(enumEventUart2Rxd,uart2rxd_callback);
SetEventCallBack(enumEventKey,key_callback);
MySTC_Init();
while(1)
{
MySTC_OS();
}
}
void uart2rxd_callback(){
unsigned char sum = 0x00;
int i;
for(i=0;i<5;i++){
sum+=rxd[i];
}
LedPrint(sum);
}
void key_callback(){
if(GetKeyAct(enumKey1)==enumKeyPress)
Uart2Print(buffer, 5);
}
3.红外无线通信
#include "STC15F2K60S2.H" //必须。
#include "sys.H" //必须。
#include "displayer.h"
#include "key.h"
#include "IR.h"
code unsigned long SysClock=11059200; //必须。定义系统工作时钟频率(Hz),用户必须修改成与实际工作频率(下载时选择的)一致
#ifdef _displayer_H_ //显示模块选用时必须。(数码管显示译码表,用戶可修改、增加等)
code char decode_table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x08,0x40,0x01,0x41,0x48,0x76,0x38,0x40,0x00,
/* 序号: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 */
/* 显示: 0 1 2 3 4 5 6 7 8 9 (无) 下- 中- 上- 上中- 中下- H L - (无)*/
0x3f|0x80,0x06|0x80,0x5b|0x80,0x4f|0x80,0x66|0x80,0x6d|0x80,0x7d|0x80,0x07|0x80,0x7f|0x80,0x6f|0x80 };
/* 带小数点 20 21 22 23 24 25 26 27 28 29 */
#endif
unsigned char rxd[5];
unsigned char buffer[5] = {0x01,0x01,0x01,0x01,0x01};
void ir_callback();
void key_callback();
void main()
{
//初始化
KeyInit();
IrInit(NEC_R05d);
DisplayerInit();
SetDisplayerArea(0,7);
Seg7Print(10,10,10,10,10,10,10,10);
SetIrRxd(rxd,5);
//设置回调
SetEventCallBack(enumEventIrRxd,ir_callback);
SetEventCallBack(enumEventKey,key_callback);
MySTC_Init();
while(1)
{
MySTC_OS();
}
}
void ir_callback(){
unsigned char sum = 0x00;
int i;
for(i=0;i<5;i++){
sum+=rxd[i];
}
LedPrint(sum);
}
void key_callback(){
if(GetKeyAct(enumKey1)==enumKeyPress)
IrPrint(buffer, 5);
}
4.实时时钟
使用实时时钟模块以及显示模块显示时间。定义一个实时时钟数据结构用于校准时钟。写RTC校准时间,设置回调函数读取RTC时间并更新显示在数码管,显示时注意RTC值为BCD码。
//******* 用户程序段1:用户程序包含文件 *************
#include "STC15F2K60S2.H" //必须。
#include "sys.H" //必须。
#include "displayer.H"
#include "DS1302.h"
code unsigned long SysClock=11059200; //必须。定义系统工作时钟频率(Hz),用户必须修改成与实际工作频率(下载时选择的)一致
#ifdef _displayer_H_ //显示模块选用时必须。(数码管显示译码表,用戶可修改、增加等)
code char decode_table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x08,0x40,0x01, 0x41, 0x48,
/* 序号: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */
/* 显示: 0 1 2 3 4 5 6 7 8 9 (无) 下- 中- 上- 上中- 中下- */
0x3f|0x80,0x06|0x80,0x5b|0x80,0x4f|0x80,0x66|0x80,0x6d|0x80,0x7d|0x80,0x07|0x80,0x7f|0x80,0x6f|0x80 };
/* 带小数点 0 1 2 3 4 5 6 7 8 9 */
#endif
unsigned char x[45];
float a,b,c,d;
struct_DS1302_RTC time={0x30,0,3,22,8,1,0x22};
struct_DS1302_RTC tmp;
void my1mS_callback()
{
tmp=RTC_Read();
Seg7Print(tmp.hour/16,tmp.hour%16,12,tmp.minute/16,tmp.minute%16,12,tmp.second/16,tmp.second%16);
}
void main() {
DisplayerInit();
SetDisplayerArea(0,7);
Seg7Print(10,10,10,10,10,10,10,10);
DS1302Init(time);
RTC_Write(time);
SetEventCallBack(enumEventSys1mS, my1mS_callback);
MySTC_Init();
while(1){
MySTC_OS();
}
}
从下题起代码没有贴头文件和数码管的decode_table。
5.非易失存储
使用M24C02模块存储数据。读出地址0x01的值并+1,再写回地址0x01,并将该值通过led显示。
void main()
{
unsigned char x;
DisplayerInit();
x = M24C02_Read(0x01) + 1;
M24C02_Write(0x01, x);
SetDisplayerArea(0,7);
Seg7Print(10,10,10,10,10,10,10,10);
LedPrint(x);
MySTC_Init();
while(1)
{
MySTC_OS();
}
}
6.收音机
使用收音机模块。初始化后定义一个收音机参数结构设置参数为91.8MHz,音量6。
void main()
{
struct_FMRadio radio = {918,6,1,0,0};
FMRadioInit(radio);
MySTC_Init();
while(1)
{
MySTC_OS();
}
}
7.音乐播放器
使用音乐模块进行播放。定义一段音乐编码,每个发音编码成对出现,音高1字节,节拍1字节。对蜂鸣器和音乐模块初始化,设置音乐编码的位置,音调与bpm,然后开始播放。
code unsigned char song[]={0x21,0x10,0x21,0x10,0x25,0x10,0x25,0x10,0x26,0x10,0x26,0x10,0x25,0x10};
void main()
{
BeepInit();
MusicPlayerInit();
SetMusic(90,0xFA,&song,sizeof(song),enumMscNull);
SetPlayerMode(enumModePlay);
MySTC_Init();
while(1)
{
MySTC_OS();
}
}
8.温度值计算
温度值的获取和显示需要使用显示模块和模数转换模块。根据参考资料中的温度/光照测量,通过GetADC()获取10位ad值并将其转换为8位ad值,取多次值求平均值减小误差,并将这个平均值显示在数码管上。设定两个回调函数,一个每1ms取一次ad值,取200个值后求均值并查表更新温度结果。另一个回调函数每1s更新一次数码管显示的温度值。
unsigned int adc_10bit = 0; //热敏电阻adc 10bit
unsigned long sumt = 0; //求和
unsigned int data_temp = 0; //四舍五入的均值
unsigned int t = 0; //计数
unsigned int flag; //符号位
int temp = 0;
struct_ADC adc_data;
//温度值对应表
int code tempdata[]={239,197,175,160,150,142,135,129,124,120,116,113,109,107,104,101,
99, 97, 95, 93, 91, 90, 88, 86, 85, 84, 82, 81, 80, 78, 77, 76,
75, 74, 73, 72, 71, 70, 69, 68, 67, 67, 66, 65, 64, 63, 63, 62,
61, 61, 60, 59, 58, 58, 57, 57, 56, 55, 55, 54, 54, 53, 52, 52,
51, 51, 50, 50, 49, 49, 48, 48, 47, 47, 46, 46, 45, 45, 44, 44,
43, 43, 42, 42, 41, 41, 41, 40, 40, 39, 39, 38, 38, 38, 37, 37,
36, 36, 36, 35, 35, 34, 34, 34, 33, 33, 32, 32, 32, 31, 31, 31,
30, 30, 29, 29, 29, 28, 28, 28, 27, 27, 27, 26, 26, 26, 25, 25,
24, 24, 24, 23, 23, 23, 22, 22, 22, 21, 21, 21, 20, 20, 20, 19,
19, 19, 18, 18, 18, 17, 17, 16, 16, 16, 15, 15, 15, 14, 14, 14,
13, 13, 13, 12, 12, 12, 11, 11, 11, 10, 10, 9, 9, 9, 8, 8, 8, 7,
7, 7, 6, 6,5, 5, 54,4, 3, 3,3, 2, 2, 1, 1, 1, 0, 0, -1, -1, -1,
-2, -2, -3, -3, -4, -4, -5, -5, -6, -6, -7, -7, -8, -8, -9, -9,
-10, -10, -11, -11, -12, -13, -13, -14, -14, -15, -16, -16, -17,
-18, -19, -19, -20, -21, -22, -23, -24, -25, -26, -27, -28, -29,
-30, -32, -33, -35, -36, -38, -40, -43, -46, -50, -55, -63, 361};
//1s更新一次温度值
void displayer1s_callback(){
Seg7Print(10,10,10,10,10,flag,temp/10,temp%10);
}
//取多个值求均值
void adc1ms_callback(){
t++;
if(t==200){
data_temp=(sumt+t/2)/t; //四舍五入
temp=tempdata[data_temp-1]; //查找对应的AD的温度值
if(temp<0){
flag = 12; //若温度为负,显示负号
}
else{
flag = 0;
}
sumt=0;
t=0;
}
adc_data = GetADC();
adc_10bit = adc_data.Rt;
data_temp=adc_10bit>>2; //由10位AD值转换为8位AD值
sumt+=data_temp; //求t次AD值的和
}
void main()
{
DisplayerInit();
SetDisplayerArea(0,7);
AdcInit(ADCexpEXT);
SetEventCallBack(enumEventSys1mS,adc1ms_callback);
SetEventCallBack(enumEventSys1S,displayer1s_callback);
MySTC_Init();
while(1)
{
MySTC_OS();
}
}
9.扩展模板
使用EXT模块和显示模块。初始化ext接口功能为超声波测距,设置回调函数,每1s更新一次超声波测距的值。
void ext_callback(){
int dis = GetUltraSonic();
Seg7Print(10,10,10,10,10,10,dis/10,dis%10);
}
void main()
{
EXTInit(enumEXTUltraSonic);
displayerInit();
SetDisplayerArea(0,7);
SetEventCallBack(enumEventSys1S,ext_callback);
MySTC_Init();
while(1)
{
MySTC_OS();
}
}
10.直流电机
使用电机模块和按键模块。按下按键1,2控制电机正转,反转。正转时速度为50%。反转时速度为30%。
void key_callback(){
if(GetKeyAct(enumKey1)==enumKeyPress){
SetPWM(50, 10, 0, 0);
}
else if(GetKeyAct(enumKey2)==enumKeyPress){
SetPWM(0, 0, 30, 10);
}
}
void main()
{
KeyInit();
EXTInit(enumEXTPWM );
SetEventCallBack(enumEventKey,key_callback);
MySTC_Init();
while(1)
{
MySTC_OS();
}
}