1、2个或以上同学相互连接,利用CAN通信,向对方发送带有本人姓名的信息。连线方式:按基本原理性电路(不带收发器芯片)连接,参考教材图10-1。
2、在ADC实验中,结合热敏电阻,分别通过触摸芯片表面和热敏电阻,引起A/D值变化,显示芯片内部温度和当前温度。
3、用实验验证,对于有数据的某扇区,如果没有擦除(Flash_erase),可否写入新数据?注:扇区号为学号 后2位,数据文本中要有姓名。
四、程序源码
内容1:can总线连接互相发送信息:
五、运行结果
用适当的文字、截图、图片等描述实验的结果,实验1需包含连线图。
Main.c
#define GLOBLE_VAR
#include "includes.h" //包含总头文件
//----------------------------------------------------------------------
//声明使用到的内部函数
//----------------------------------------------------------------------
//主函数,一般情况下可以认为程序从此开始运行(实际上有启动过程,参见书稿)
int main(void)
{
//(1)======启动部分(开头)==========================================
//(1.1)声明main函数使用的局部变量
vuint32_t mMainLoopCount; //主循环次数变量
uint8_t mFlag; //灯的状态标志
uint32_t mLightCount; //灯的状态切换次数
uint32_t localMsgID;
uint32_t txMsgID;
uint32_t BitRate;
//(1.2)【不变】关总中断
DISABLE_INTERRUPTS;
//(1.3)给主函数使用的局部变量赋初值
mMainLoopCount=0; //主循环次数变量
mFlag='A'; //灯的状态标志
mLightCount=0; //灯的闪烁次数
localMsgID = 0x0BU;
txMsgID = 0x0AU;
BitRate = 36;
//(1.4)给全局变量赋初值
//(1.5)用户外设模块初始化
gpio_init(LIGHT_RED,GPIO_OUTPUT,LIGHT_ON); //初始化蓝灯
emuart_init(UART_User,115200);
uart_init(UART_3,115200);
//【***CAN模块初始化***】
can_init(CAN_1,localMsgID,BitRate);
//(1.6)使能模块中断
uart_enable_re_int(UART_User);
uart_enable_re_int(UART_3);
//【***使能CAN模块中断***】
can_enable_recv_int(CAN_1);
//(1.7)【不变】开总中断
ENABLE_INTERRUPTS;
//(1)======启动部分(结尾)==========================================
//(2)======主循环部分(开头)========================================
for(;;) //for(;;)(开头)
{
//(2.1)主循环次数变量+1
mMainLoopCount++;
//(2.2)未达到主循环次数设定值,继续循环
if (mMainLoopCount<=12889000) continue;
//(2.3)达到主循环次数设定值,执行下列语句,进行灯的亮暗处理
//(2.3.1)清除循环次数变量
mMainLoopCount=0;
//(2.3.2)如灯状态标志mFlag为'L',灯的闪烁次数+1并显示,改变灯状态及标志
if (mFlag=='L') //判断灯的状态标志
{
mLightCount++;
printf("灯的闪烁次数 mLightCount = %d\n",mLightCount);
mFlag='A'; //灯的状态标志
gpio_set(LIGHT_RED,LIGHT_ON); //灯"亮"
printf(" LIGHT_RED:ON--\n"); //串口输出灯的状态
//【***CAN模块发送一帧数据***】
if(can_send(CAN_1, txMsgID, 8, (uint8_t*)"IamnodeB") != 0) printf("failed\r\n");
}
//(2.3.3)如灯状态标志mFlag为'A',改变灯状态及标志
else
{
mFlag='L'; //灯的状态标志
gpio_set(LIGHT_RED,LIGHT_OFF); //灯"暗"
printf(" LIGHT_RED:OFF--\n"); //串口输出灯的状态
}
} //for(;;)结尾
//(2)======主循环部分(结尾)========================================
} //main函数(结尾)
//======以下为主函数调用的子函数===========================================
//========================================================================
/*
知识要素:
(1)main.c是一个模板,该文件所有代码均不涉及具体的硬件和环境,通过调用构件
实现对硬件的干预。
(2)本文件中对宏GLOBLE_VAR进行了定义,所以在包含"includes.h"头文件时,会定
义全局变量,在其他文件中包含"includes.h"头文件时,
编译时会自动增加extern
*/
内容2:在ADC实验中,结合热敏电阻,分别通过触摸芯片表面和热敏电阻,引起A/D值变化,显示芯片内部温度和当前温度。
//主函数
int main(void)
{
uint16_t num_AD1;
uint16_t num_AD2;
uint16_t num_AD3;
uint32_t mMainLoopCount; //主循环次数变量
//关总中断
DISABLE_INTERRUPTS;
mMainLoopCount=0; //主循环次数变量
adc_init(ADC_CHANNEL_1,AD_DIFF); //初始化ADC通道1,
adc_init(ADC_CHANNEL_15,AD_DIFF); //初始化ADC通道15
adc_init(ADC_CHANNEL_TEMPSENSOR,AD_SINGLE); //初始化ADC通道:内部温度
ENABLE_INTERRUPTS;
printf("------------------------------------------------------\n");
printf("金葫芦提示: \n");
printf("(1)目的:ADC单端输入与差分输入测试 \n");
printf("(2)单端:内部温度传感器,通道号17,无需引脚对应 \n");
printf(" 差分:GEC引脚47、46(通道1、2) \n");
printf(" GEC引脚12、11(通道15、16) \n");
printf("(3)测试方法:单端:手摸芯片表面,A/D值增大,不要摸 \n");
printf(" 到引脚,静电可能损坏芯片 \n");
printf(" 差分:将引脚47接地、46接3.3V,观察通道1情况\n");
printf(" 将引脚46接地、47接3.3V,观察通道1情况\n");
printf(" 类似方法,观察通道15 \n");
printf("------------------------------------------------------\n");
for(;;)
{
//主循环次数变量+1
mMainLoopCount++;
//未达到主循环次数设定值,继续循环
//延时1秒
if (mMainLoopCount<=30000000) continue;
//达到主循环次数设定值,执行下列语句,进行灯的亮暗处理
//清除循环次数变量
mMainLoopCount=0;
num_AD1 = adc_ave(ADC_CHANNEL_1,8);
num_AD2 = adc_ave(ADC_CHANNEL_15,8);
num_AD3 = adc_ave(ADC_CHANNEL_TEMPSENSOR,8);
printf("通道1(GEC47、46)的A/D值: %d\r\n",num_AD1);
printf("通道1(GEC47、46)的温度值: %f\r\n",Regression_Ext_Temp(num_AD1));
printf("通道15(GEC12、11)的A/D值:%d\r\n",num_AD2);
printf("通道15(GEC12、11)的温度值:%f\r\n",Regression_Ext_Temp(num_AD2));
printf("32106100129内部温度A/D值:%d\r\n",num_AD3);
printf("梁毅轩内部温度温度值:%f\r\n\n",Regression_MCU_Temp(num_AD3));
}
}
内容三:
用实验验证,对于有数据的某扇区,如果没有擦除(Flash_erase),可否写入新数据?注:扇区号为学号 后2位,数据文本中要有姓名。
首先写入数据:
int main(void)
{
uint8_t mK1[32]; //按照逻辑读方式从指定flash区域中读取的数据
uint8_t result; //判断扇区是否为空标识
uint16_t sector = 29U;
//初始化扇区内容
flash_erase(sector);
flash_write(sector,0,32,(uint8_t *) "Iam32106100129梁毅轩");
printf("初始化%d扇区。\n",sector);
flash_read_logic(mK1,sector,0,32); //从指定扇区读取32个字节到mK1中
printf("擦除前%d扇区32字节的内容:%s\n",sector,mK1);
result = flash_isempty(sector,MCU_SECTORSIZE); // 判断指定扇区是否为空
printf("扇区判空,1空,0不空:%d\n",result);
//擦除指定扇区
flash_erase(sector);
printf("\n擦除%d扇区。\n",sector);
flash_read_logic(mK1,sector,0,32); //从指定扇区读取32个字节到mK1中
printf("擦除后%d扇区32字节的内容:%s\n",sector,mK1);
result = flash_isempty(sector,MCU_SECTORSIZE); // 判断指定扇区是否为空
printf("扇区判空,1空,0不空:%d\n",result);
//向指定扇区第0偏移地址开始写32个字节数据
flash_write(sector,0,32,(uint8_t *) "广州大学!32106100129梁毅轩");
printf("\n写入%d扇区。\n",sector);
flash_read_logic(mK1,sector,0,32); //从指定扇区读取32个字节到mK1中
printf("写入后%d扇区32字节的内容:%s\n",sector,mK1);
result = flash_isempty(sector,MCU_SECTORSIZE); // 判断指定扇区是否为空
printf("扇区判空,1空,0不空:%d\n",result);
for(;;) //for(;;)(开头)
{
}
}
//======以下为主函数调用的子函数===========================================
//========================================================================
/*
知识要素:
(1)main.c是一个模板,该文件所有代码均不涉及具体的硬件和环境,通过调用构件
实现对硬件的干预。
(2)本文件中对宏GLOBLE_VAR进行了定义,所以在包含"includes.h"头文件时,会定
义全局变量,在其他文件中包含"includes.h"头文件时,
编译时会自动增加extern
*/
擦除后得验证:
//======================================================================
//文件名称:main.c(应用工程主函数)
//框架提供:SD-Arm(sumcu.suda.edu.cn)
//版本更新:20191108-20200419
//功能描述:见本工程的..\01_Doc\Readme.txt
//移植规则:【固定】
//======================================================================
#define GLOBLE_VAR
#include "includes.h" //包含总头文件
//----------------------------------------------------------------------
//声明使用到的内部函数
//----------------------------------------------------------------------
//主函数,一般情况下可以认为程序从此开始运行(实际上有启动过程,参见书稿)
//主函数
int main(void)
{
uint8_t mK1[32]; //按照逻辑读方式从指定flash区域中读取的数据
uint8_t result; //判断扇区是否为空标识
uint16_t sector = 92U;//因为我的学号后两位29不知为何无法执行,因此调换顺序
//初始化扇区内容
flash_erase(sector);
flash_write(sector,0,32,(uint8_t *) "789546");
printf("初始化%d扇区。\n",sector);
flash_read_logic(mK1,sector,0,32); //从指定扇区读取32个字节到mK1中
printf("擦除前%d扇区32字节的内容:%s\n",sector,mK1);
result = flash_isempty(sector,MCU_SECTORSIZE); // 判断指定扇区是否为空
printf("扇区判空,1空,0不空:%d\n",result);
//擦除指定扇区
flash_erase(sector);
printf("\n擦除%d扇区。\n",sector);
flash_read_logic(mK1,sector,0,32); //从指定扇区读取32个字节到mK1中
printf("擦除后%d扇区32字节的内容:%s\n",sector,mK1);
result = flash_isempty(sector,MCU_SECTORSIZE); // 判断指定扇区是否为空
printf("扇区判空,1空,0不空:%d\n",result);
//向指定扇区第0偏移地址开始写32个字节数据
flash_write(sector,0,32,(uint8_t *) "广州大学!32106100129梁毅轩");
printf("\n写入%d扇区。\n",sector);
flash_read_logic(mK1,sector,0,32); //从指定扇区读取32个字节到mK1中
printf("写入后%d扇区32字节的内容:%s\n",sector,mK1);
result = flash_isempty(sector,MCU_SECTORSIZE); // 判断指定扇区是否为空
printf("扇区判空,1空,0不空:%d\n",result);
for(;;) //for(;;)(开头)
{
}
}
//======以下为主函数调用的子函数===========================================
//========================================================================
/*
知识要素:
(1)main.c是一个模板,该文件所有代码均不涉及具体的硬件和环境,通过调用构件
实现对硬件的干预。
(2)本文件中对宏GLOBLE_VAR进行了定义,所以在包含"includes.h"头文件时,会定
义全局变量,在其他文件中包含"includes.h"头文件时,
编译时会自动增加extern
*/
实验结果截图以及实例:
内容1:
连接设备
发送信息:
内容二:
内容3:
写入:
验证:
结论:未擦除无法写入新数据。
六、分析思考
通过本次实验,我深刻体会到了嵌入式系统设计的复杂性和挑战性。我学习到了如何综合运用硬件知识和软件编程技能来解决实际问题。
在实验过程中,我首先学习了CAN总线的工作原理和通信协议。通过实践,我掌握了如何配置CAN控制器和编写相应的通信代码。
在ADC温度检测部分,我学习了模拟信号到数字信号的转换过程,并编写了相应的采集程序