第一篇:浙工大 嵌入式实验报告
金艳霞
通信2班
201203110210
实验五 Linux交叉编译平台
一、实验目的
1.掌握一些基本的linux读写操作 2.利用vcc编译c程序
3.通过nfs挂载到实验箱中,利用交叉编译执行文件
二.实验设备
1.Arm9试验箱 2.Pc机
3.Linux系统服务器
三.实验过程及实验结果 1.连接电脑箱
2.设置交叉编译环境 启动putty.exe 登陆192.168.1.116
3.添加软件包至实验目录: ① [shiyan@localhost ~]$ cd /home/shiyan ② [shiyan@localhost ~]$ tar –zxvf arm-linux-gcc-3.4.4-glib-2.3.5-static.tar.gz tar-zxvf arm-linux-gcc-3.4.4-glib-2.3.5-static.tar.gz ③ [shiyan@localhost201203110210] $export PATH=$PATH:/home/shiyan/201203110210/opt/crosstool/arm-linux/gcc-3.4.4-glib-2.3.5/arm-linux/bin ④ [shiyan@localhost 201203110210]$ set OSTYPE=linux-gnu PATH=/usr/lib/qt-3.3/bin:/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/home/shiyan/bin:/home/shiyan/opt/crosstool/arm-linux/gcc-3.4.4-glibc-2.3.5/arm-linux/bin:/home/shiyan/opt/crosstool/arm-linux/gcc-3.4.4-glibc-2.3.5/arm-linux/bin:/home/shiyan/opt/crosstool/arm-linux/gcc-3.4.4-glibc-2.3.5/arm-linux/bin 可以看出路径已添加 ⑤ [shiyan@localhost 201203110210]$ arm-linux-g再按tab arm-linux-g++
arm-linux-gcc
arm-linux-gcc-3.4.4 arm-linux-gccbug
arm-linux-gcov ⑥ [shiyan@localhost 201203110210]$ arm-linux-gcc arm-linux-gcc: no input files 此时出错,无此文件 3.测试程序 ① 创建hello.c [shiyan@localhost ~]$ vi hello.c #include
:wq ② 查看是否生成文件
[shiyan@matrix 201203110210]$ ls arm-linux-gcc-3.4.4-glib-2.3.5-static.tar.gz hello.c 已经生成 ③ 打开hello.c [shiyan@localhost ~]$./hello.c-bash:/hello cannot execute binary file 表示无法在服务器上执行 ④ 交叉编译hello.c [shiyan@localhost ~]$ arm-linux-gcc-o hello hello.c ⑤ 将文件拷贝到nfs下
[shiyan@localhost ~]$ cp hello /home/shiyan/nfs ⑥ 挂载服务器到板子上
/ $ mount –tnfs-o nolock 192.168.1.116:/home/shiyan/nfs/mnt/nfs / $cdmnt/nfs ⑦ 打开hello文件 / $./hello
结果输出: Jin 123
四.实验总结
上述实验可以得出,交叉编译的二进制可以在板子上运行,却不能在服务器上运行,很好的认清了交叉编译的意义和功能。
实验六Armboot下载运行及tcp实验
一.实验目的
1.掌握armboot的编译 2.掌握tftp工具的使用 3.掌握armboot下载运行
4.掌握windows的 tcp客户端的建立及通信过程 5.掌握tcp的基本原理
二.实验设备
1.Arm9试验箱 2.Pc机
3.Linux系统服务器
三.实验过程及实验结果 1)Armboot
① 编译armboot-1.1.0 cd /home/shiyan/arm-linux-2.6/armboot-1.1.0 [shiyan@matrix armboot-1.1.0]$ make
② 产生的armboot.bin拷贝到tftp的目录服务下
[shiyan@matrixarmboot-1.1.0]$ cparmboot.bin /home/shiyan/arm-linux-2.6/armboot-1.1.0/tftpboot/armboot ③ 打开arm9开发板,在五秒内按ESC,检查网络环境
CPE>printenv bootdelay=3 baudrate=38400 ethaddr=00:40:25:00:00:01 netmask=255.255.255.0 sererip=192.168.1.65 ipaddr=192.168.1.111 serverip=192.168.1.30
Environment size: 139/131068 bytes ④ 将armboot的网络环境改为tftp服务的网络地址
setenv serverip 192.168.1.220 CPE>saveenv Un-Protected 1 sectors Erasing sector 6...ok.0x800e0000
o Flash...done.Protected 1 sectors
⑤ 将armboot.bin文件通过tftp传输到内存0x2000000H中
CPE>tftp 0x2000000 armboot.bin ARP broadcast 1 ARP broadcast 2
⑥ 运行
go 0x2000000
⑦ 检查网络环境
CPE> printenv bootdelay=3 baudrate=38400 ethaddr=00:40:25:00:00:01 netmask=255.255.255.0 sererip=192.168.1.65 ipaddr=192.168.1.111 serverip=192.168.1.220
通过serverip的改变可看出armboot下载的正确性。
实验七 Mount挂载实验
一.实验目的 1.掌握一些基本的linux读写操作(touch指令)2.掌握Usb挂载方法 3.掌握配置nfs的方法
二.实验设备
1.2.3.4.Arm9试验箱 Pc机
Linux系统服务器 U盘
三.实验过程及实验结果 A.文件夹挂载 1.服务器
[shiyan@matrix ~]$/etc/rc.d/init.d/nfs start 2.板子挂载
/ $ ifconfig eth0 192.168.1.98 / $ mount-t nfs-o nolock 192.168.1.220:/home/shiyan/nfs/mnt/nfs /$ df Filesystem
1k-blocks
Used Available Use% Mounted on /dev/mtdblock1
1024
544
480 53% /mnt/mtd 192.168.1.220:/home/shiyan/nfs 515455456 59590720 429681056 12% /mnt/nfs B.Usb 挂载
① 将u盘插入arm9开发板,并启动 ② 查看盘符信息
/ $ fdisk-l
③ 创建一个/mnt/usb文件夹
/ $ mkdir /mnt/usb ④ 把sda1盘符mount到/mnt/usb文件上
/ $ mount /dev/sda1 /mnt/usb/ / $ cd /mnt/usb /mnt/usb $ ls
⑤ 创建文件,并输入字符串
/mnt/usb $ vi jin.txt
hello!
⑥ 解挂载
/mnt/usb $ unmount /mnt/usb/ /bin/sh: unmount: not found ⑦ 将u盘拔出,插入电脑,观察该文件
结果正确
实验八RTC时钟驱动实验
一.实验目的
1.了解RTC工作原理 2.掌握RTC时钟驱动编程
二.实验内容
1.编写RTC驱动程序
2.通过insmod加载驱动程序 3.编写代码修改RTC内部时间
三.实验设备
1.PC机
2.Arm9实验箱客户端 3.Linux操作系统服务端
四.实验过程及结果
1.实验代码
#include
“0.01” /* Register map */ /* rtc section */ // control and status registers #define REG_CS1 0x00
#define TEST1
(1<<7)
// 0-normal mode, must be set to logic 0 during normal operations;1-EXT_CLK test mode #define STOP
(1<<5)
// 0-RTC source clock runs;1-the RTC clock is stopped(CLKOUT at 32.768KHz is still available)#define TESTC
(1<<3)
// 0-power-on reset(POR)override facility is disable;set to logic 0 for normal operation;1-POR override may be enable #define REG_CS2 0x01 #define TI_TP
(1<<4)
// 0-int is active when TF is active(subject to the status of TIE)#define AF
(1<<3)#define TF
(1<<2)#define AIE
(1<<1)#define TIE
(1<<0)
// Time and date registers #define REG_SC 0x02
// vl_seconds(0-59)#define REG_MN 0x03
// minutes(0-59)#define REG_HR 0x04
// hours(0-23)#define REG_DT 0x05
// days(1-31)#define REG_DW 0x06
// weekdays(0-6)#define REG_MO 0x07
// century_months(1-12)#define REG_YR 0x08
// years(0-99)
// Alarm registers #define REG_MA 0x09
// minute_alarm #define AE_M
(1<<7)#define REG_HA 0x0a
// hour_alarm #define AE_H
(1<<7)#define REG_DA 0x0b
// day_alarm #define AE_D
(1<<7)#define REG_WA 0x0c
// weekday_alarm #define AE_W
(1<<7)// CLKOUT control register #define REG_CC 0x0d #define FE
(1<<7)// Timer registers #define REG_TC 0x0e
// timer_control #define TE
(1<<7)#define REG_TMR 0x0f
// timer #define RTC_SECTION_LEN
/* i2c configuration */ #define I2C_ADDR
0xa2 ///////////////////////////////////////////////////////////// #define DEFAULT_I2C_CLOCKDIV
180//for APB 108MHz staticunsignedlong rtc_status;staticvolatileunsignedlong rtc_irq_data;staticunsignedlong rtc_freq = 1;/*FTRTC010 supports only 1Hz clock*/ staticstruct fasync_struct *rtc_async_queue;static DECLARE_WAIT_QUEUE_HEAD(rtc_wait);extern spinlock_t rtc_lock;MODULE_AUTHOR(“GM Corp.”);MODULE_LICENSE(“GM License”);externint GM_i2c_xfer(struct i2c_msg *msgs, int num, int clockdiv);/* block read */ staticint i2c_read_regs(u8 reg, u8 buf[], unsigned len){ struct i2c_msg msgs[1];//////////////
buf[0] = reg;
msgs[0].addr = I2C_ADDR>>1;
msgs[0].flags = 0;
msgs[0].len = 1;
msgs[0].buf = buf;
if(GM_i2c_xfer(msgs, 1, DEFAULT_I2C_CLOCKDIV)!= 1)return-1;//////////////
msgs[0].addr = I2C_ADDR>>1;
msgs[0].flags = 1;
msgs[0].len = len+1;
msgs[0].buf = buf;
if(GM_i2c_xfer(msgs, 1, DEFAULT_I2C_CLOCKDIV)!= 1)return-1;return 0;} /* block write */ staticint i2c_set_regs(u8 reg, u8 const buf[], unsigned len){
u8 i2c_buf[10];struct i2c_msg msgs[1];
i2c_buf[0] = reg;
memcpy(&i2c_buf[1], &buf[0], len);
msgs[0].addr = I2C_ADDR>>1;
msgs[0].flags = 0;
msgs[0].len = len+1;
msgs[0].buf = i2c_buf;
if(GM_i2c_xfer(msgs, 1, DEFAULT_I2C_CLOCKDIV)!= 1)return-1;return 0;} staticint set_time(struct rtc_time const *tm){ int sr;
u8 regs[RTC_SECTION_LEN] = { 0, };
printk(“stop RTCn”);
regs[0] = STOP;
regs[1] = 0x00;
// disable interrupt and clear all flags
sr = i2c_set_regs(REG_CS1, regs, 2);if(sr < 0){
// write control and status registers
printk(“%s: stop RTC failedn”, __func__);return sr;
}
printk(“set_time Date(y/m/d):%d/%d/%d Time(h/m/s):%d/%d/%dn”,tm->tm_year,tm->tm_mon,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec);
regs[REG_SC-REG_SC] = BIN2BCD(tm->tm_sec);
regs[REG_MN-REG_SC] = BIN2BCD(tm->tm_min);
regs[REG_HR-REG_SC] = BIN2BCD(tm->tm_hour);
regs[REG_DT-REG_SC] = BIN2BCD(tm->tm_mday);
regs[REG_MO-REG_SC] = BIN2BCD(tm->tm_mon);
regs[REG_YR-REG_SC] = BIN2BCD(tm->tm_year-100);
regs[REG_DW-REG_SC] = BIN2BCD(tm->tm_wday & 7);/* write RTC registers */
sr = i2c_set_regs(REG_SC, regs, RTC_SECTION_LEN);if(sr < 0){
printk(“%s: writing RTC section failedn”, __func__);return sr;
}
printk(“start RTCn”);
regs[0] = 0x00;
sr = i2c_set_regs(REG_CS1, regs, 1);if(sr < 0){
// write control and status registers
printk(“%s: start RTC failedn”, __func__);return sr;
}
return 0;
} staticvoid read_time(struct rtc_time *tm){ int sr;
u8 regs[RTC_SECTION_LEN] = { 0, };
sr = i2c_read_regs(REG_SC, regs, RTC_SECTION_LEN);if(sr < 0){
printk(“%s: reading RTC section failedn”, __func__);return;
}
tm->tm_sec = BCD2BIN(regs[REG_SC-REG_SC]&0x7f);
tm->tm_min = BCD2BIN(regs[REG_MN-REG_SC]&0x7f);
tm->tm_hour = BCD2BIN(regs[REG_HR-REG_SC]&0x3f);
tm->tm_mday = BCD2BIN(regs[REG_DT-REG_SC]&0x3f);
tm->tm_wday = BCD2BIN(regs[REG_DW-REG_SC]&0x07);
tm->tm_mon = BCD2BIN(regs[REG_MO-REG_SC]&0x1f);/* rtc starts at 1 */
tm->tm_year = BCD2BIN(regs[REG_YR-REG_SC])+100;
printk(“read_time Date(YY/MM/DD):%d/%d/%d Time(hh/mm/ss):%d/%d/%dn”,tm->tm_year,tm->tm_mon,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec);} staticunsigned AIE_stat=0;/*ijsung: arch-indep function*/ staticint rtc_open(struct inode *inode, struct file *file){ if(test_and_set_bit(1, &rtc_status))return-EBUSY;
rtc_irq_data = 0;return 0;} staticint rtc_release(struct inode *inode, struct file *file){ unsignedchar buf[7];
rtc_status = 0;return 0;} staticint rtc_fasync(int fd, struct file *filp, int on){ return fasync_helper(fd, filp, on, &rtc_async_queue);} staticunsignedint rtc_poll(struct file *file, poll_table *wait){
poll_wait(file, &rtc_wait, wait);return(rtc_irq_data)? 0 : POLLIN | POLLRDNORM;} static loff_t rtc_llseek(struct file *file, loff_t offset, int origin){ return-ESPIPE;} ssize_t rtc_read(struct file *file, char *buf, size_t count, loff_t *ppos){
DECLARE_WAITQUEUE(wait, current);unsignedlong data;
ssize_t retval;if(count add_wait_queue(&rtc_wait, &wait); set_current_state(TASK_INTERRUPTIBLE);for(;;){ spin_lock_irq(&rtc_lock); data = rtc_irq_data;if(data!= 0){ rtc_irq_data = 0;break; } spin_unlock_irq(&rtc_lock);if(file->f_flags & O_NONBLOCK){ retval =-EAGAIN;goto out; } if(signal_pending(current)){ retval =-ERESTARTSYS;goto out; } schedule(); } spin_unlock_irq(&rtc_lock); data-= 0x100;/* the first IRQ wasn't actually missed */ retval = put_user(data,(unsignedlong *)buf);if(!retval) retval = sizeof(unsignedlong);out: set_current_state(TASK_RUNNING); remove_wait_queue(&rtc_wait, &wait);return retval;} staticint rtc_ioctl(struct inode *inode, struct file *file, unsignedint cmd, unsignedlong arg){ struct rtc_time tm, tm2;unsignedchar buf[7];switch(cmd){ case RTC_AIE_OFF: printk(“Not Supportn”);return 0;case RTC_AIE_ON: printk(“Not Supportn”);return 0;case RTC_ALM_READ: printk(“Not Supportn”);return 0;case RTC_ALM_SET: printk(“Not Supportn”);return 0;case RTC_RD_TIME: read_time(&tm);break; case RTC_SET_TIME: { unsigned usertime;unsignedchar buf[7];if(!capable(CAP_SYS_TIME))return-EACCES;if(copy_from_user(&tm,(struct rtc_time*)arg, sizeof(tm)))return-EFAULT; set_time(&tm); } return 0;case RTC_IRQP_READ: return put_user(rtc_freq,(unsignedlong *)arg);case RTC_IRQP_SET: if(arg!= 1)return-EINVAL;return 0;case RTC_EPOCH_READ: return put_user(1970,(unsignedlong *)arg);default: return-EINVAL; } return copy_to_user((void *)arg, &tm, sizeof(tm))?-EFAULT : 0;} staticstruct file_operations rtc_fops = { owner: THIS_MODULE,llseek: rtc_llseek,read: rtc_read,poll: rtc_poll,ioctl: rtc_ioctl,open: rtc_open,release: rtc_release,fasync: rtc_fasync, };staticstruct miscdevice ftrtc010rtc_miscdev = { RTC_MINOR,“rtc”, &rtc_fops };staticint rtc_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data){ // unsigned alarm_time;unsignedchar buf[7]; char *p = page;int len;struct rtc_time tm; read_time(&tm);//printk(“RTC...%dn”,xtime.tv_sec); p += sprintf(p, “rtc_timet: %02d:%02d:%02dn” “rtc_datet: %04d-%02d-%02dn” “rtc_epocht: %04dn”,tm.tm_hour + 1, tm.tm_min, tm.tm_sec,tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, 2000);// read_alarm(&tm);// p += sprintf(p, “alrm_timet: %2dth day of week dayn” // “alrm_datet: N/A for Platformn”, // tm.tm_wday); p += sprintf(p, “alrm_timet: Not Supportn” “alrm_datet: Not Supportn”); p += sprintf(p, “alarm_IRQt: %sn”, AIE_stat ? “yes” : “no”); len =(poff;if(len < 0) len = 0; *eof =(len <= count)? 1 : 0; *start = page + off;return len;} staticint __init rtc_init(void){ misc_register(&ftrtc010rtc_miscdev); create_proc_read_entry(“driver/rtc”, 0, 0, rtc_read_proc, NULL); printk(“PCF8563 Real Time Clock drivern”);return 0;} staticvoid __exit rtc_exit(void){ remove_proc_entry(“driver/rtc”, NULL); misc_deregister(&ftrtc010rtc_miscdev);} module_init(rtc_init);module_exit(rtc_exit); 2.挂载usb / $ ifconfig eth0 192.168.1.99 / $ mount-t nfs-o nolock 192.168.1.220:/home/shiyan/nfs /mnt/nfs / $ fdisk –l / $ mkdir /mnt/usb / $ mount /dev/sda1 /mnt/usb/ / $ cd /mnt/usb 3.找到u盘中的pcf8563.ko /mnt/usb $ ls 4.加载pcf8563.ko /mnt/usb $ insmod pcf8563.ko 5.更改日期并写入 6.重启检验日期 与当前时间相符 实验九视频采集RTP发送及远程视频监控实验 一.实验目的 1.理解视频传输原理 2.掌握在IP网络中实现视频传输的方法 3.理解远程控制原理 4.掌握在windows下TCP客户端建立及通信过程 二.实验内容 1.搭建点对点视频传输模式 2.开启视频采集 3.开启Windows下tcp客户端,完成控制命令 三.实验设备 1.硬件:基于双核处理器架构的网络音视频传输教学实验系统; 对接线; 串口连接线; 网线; 集线器(HUB),PC机; 2.软件:H.264流媒体软件 设备端视频采集程序 设备端视频传输程序 串口操作软件 四.实验步骤及结果 A.视频采集 1.连接好实验箱,打开串口通信端,远程mount到home/nfs文件夹 / $ mount-t nfs-o nolock 192.168.1.116:/home/shiyan/nfs /mnt/nfs 2.挂载服务器下nfs与板子的/mnt/nfs,进入/mnt/nfs文件夹 / $ cd /mnt/nfs 3.输入ls命令,目录下文件 /mnt/nfs $ ls 123321 clientxxww readme tcpserver StartLog0 ffgpio.ko server tcpserver19 a gpio_test serverfxf tcpserver_arm_11 bo hello serverxw tcpserver_hdt client nfs1 tcpclient tcpserver_zn client_arm ok tcpclient19 tcpsever client_arm_17 program_20_1.c tcpclient_29 tw2835_menu client_arm_st20 program_20_2.c tcpclient_arm_11 xianshi client_dalan programyk tcpclient_hdt yk clientxw programyq tcpclient_zn yq 4.运行tw2835_menu进行视频采集 /mnt/nfs $./tw2835_menu& 5.进入挂载目录并查看文件 /mnt/nfs $ cd nfs1 /mnt/nfs/nfs1 $ ls dev_app.app hello vedio.confTCPS1 dev_app3 ffgpio.ko tw2835_menu dev_app gpio_test tw2835_pic 6.运行dev_app到板子IP192.168.1.9 /mnt/nfs/nfs1 $./dev_app 192.168.1.9 7.开启H.264流媒体播放器进行视频接受 a)用解码器解码,并允许注册.bat b)打开H.264流媒体播放器,点击开启视频接收 B.远程视频监控 1.重复以上实验1~4步 2.进入已挂载目录/mnt/nfs/nfs1,看到多个程序 /mnt/nfs $ cd nfs1 /mnt/nfs/nfs1 $ ls StartLog0 dev_app.app hello vedio.conf TCPS1 dev_app3 image.info www boot.sh ffgpio.ko tw2835_menu 3.运行TCPS1 /mnt/nfs/nfs1 $./ TCPS1 4.程序进入等待状态,等待TCP连接到来 5.开启H.264流媒体播放器,点击“开始视频接收”,屏幕变黑 6.点击“控制功能”,输入设备端ip地址192.168.1.68,点击连接 7.设备端出现下列字样,表示连接成功 Servergetconnectionfrom192.168.1.68 8.点击“开启视频监控”,获得视频数据 实验十一Tcp网络编程 一、实验目的 1.了解网络编程原理 2.了解套接字的使用 二、实验原理 嵌入式Linux的网络通信程序是基于套接字模式的。Socket实际是网络传输层供给应用层的接口。常见的Socket有三种类型。1.流式Sockct 流式套接字提供可靠的,面向连接的通信流,它使用TCP协议,从而保证了数据传输的正确性和顺序性。Socket编程采用客户/服务器模式。因此编程分为服务器端和客户端。服务器端:首先建立Socket,返回该Socket的描述符;配置Socket的端口和IP地址;建立监听函数,检测是否有客户端向服务器端发送请求,若有则接收该请求,将其放到接收队列中;从接收队列中接收一个请求;并向客户端发送确认连接信息。客户端:建立一个Socket,返回该Socket的描述符,配置Socket端口和IP地址;向服务器发送连接请求,并接收服务器发回的确认连接信息。双方通信结束后,关闭其Socket。2.数据报Socket,数据通过相互独立的报文进行传输,数据报套接字定义了一种无连接的服务,是无序的,并且不保证是可靠的,无差错的。它使用数据报协议UDP。3.原始Socket 使用Socket编程时可以开发客户机和服务器端应用程序,它们可以在本地网络上进行通信,也可以通过Internet在全球范围内进行通信。编写并运行Socket的客户端和服务器端程序,双方通过套接字建立了服务连接请求,并且通过一些方法提高Socket的性能。 三、实验步骤 编写服务器端源程序和客户端源程序 1.代码: program_20_1.c #include int main(int argc, char *argv[]){ int sockfd,new_fd; struct sockaddr_in server_addr; struct sockaddr_in client_addr; int portnumber; const char hello[]=“Hello and Byen”;// for setsockopt()SO_REUSEADDR, below int yes = 1;int addrlen; if(argc!=2) { fprintf(stderr,“Usage:%s portnumberan”,argv[0]); exit(1); } if((portnumber=atoi(argv[1]))<0) { fprintf(stderr,“Usage:%s portnumberan”,argv[0]); exit(1); } /* 服务器端开始建立socket描述符 */ if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) { fprintf(stderr,“Socket error:%sna”,strerror(errno)); exit(1); } printf(“Server-socket()is OK...n”); // “address already in use” error message if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,sizeof(int))==-1) { perror(“Server-setsockopt()error lol!”); exit(1); } printf(“Server-setsockopt()is OK...n”); /* 服务器端填充 sockaddr结构 */ bzero(&server_addr,sizeof(struct sockaddr_in)); server_addr.sin_family=AF_INET; server_addr.sin_addr.s_addr=htonl(INADDR_ANY); server_addr.sin_port=htons(portnumber); memset(&(server_addr.sin_zero), ' ', 8); /* 捆绑sockfd描述符 */ if(bind(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1) { fprintf(stderr,“Bind error:%sna”,strerror(errno)); exit(1); } printf(“Server-bind()is OK...n”); /* 监听sockfd描述符 */ if(listen(sockfd,5)==-1) { fprintf(stderr,“Listen error:%sna”,strerror(errno)); exit(1); } printf(“Server-listen()is OK...n”); while(1) { /* 服务器阻塞,直到客户程序建立连接 */ addrlen = sizeof(client_addr); if((new_fd=accept(sockfd,(struct sockaddr *)(&client_addr),&addrlen))==-1) { printf(“Accept error:%sna”,strerror(errno)); exit(1); }else{ printf(“Server-accept()is OK...n”);} printf(“New connection from %s on socket %dn”, inet_ntoa(client_addr.sin_addr), new_fd); if(write(new_fd,hello,strlen(hello))==-1) { printf(“Write Error:%sn”,strerror(errno)); exit(1); }else{ printf(“Write something to the client, then close it.n”); } close(new_fd); } close(sockfd); exit(0);} program_20_2.c /TCPClient示例/ #include int main(int argc, char *argv[]){ int sockfd; char buffer[1024]; struct sockaddr_in server_addr;struct hostent *host;int portnumber,nbytes;if(argc!=3){ fprintf(stderr,“Usage:%s hostname portnumberan”,argv[0]); exit(1);} if((host=gethostbyname(argv[1]))==NULL){ herror(“Get host name errorn”); exit(1);} if((portnumber=atoi(argv[2]))<0){ fprintf(stderr,“Usage:%s hostname portnumberan”,argv[0]); exit(1);} /* 客户程序开始建立 sockfd描述符 */ if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1){ fprintf(stderr,“Socket Error:%san”,strerror(errno)); exit(1);} /* 客户程序填充服务端的资料 */ bzero(&server_addr,sizeof(server_addr));server_addr.sin_family=AF_INET; server_addr.sin_port=htons(portnumber); server_addr.sin_addr=*((struct in_addr *)host->h_addr);/* 客户程序发起连接请求 */ if(connect(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1){ fprintf(stderr,“Connect Error:%san”,strerror(errno)); exit(1);} /* 连接成功了 */ if((nbytes=read(sockfd,buffer,1024))==-1){ fprintf(stderr,“Read Error:%sn”,strerror(errno)); exit(1);} buffer[nbytes]=' '; printf(“I have received:%sn”,buffer);/* 结束通讯 */ close(sockfd);exit(0);} 2.步骤 ① 交叉编译服务端程序 [shiyan@matrix ~]$ cd /home/shiyan [shiyan@localhost ~]$ gcc-o clientjin program_20_1.c [shiyan@localhost ~]$ arm-linux-gcc-o serverjin program_20_2.c [shiyan@localhost ~]$ cp /home/shiyan/serverjin /home/shiyan/nfs ② 执行 [shiyan@localhost ~]$./clientjin 3456 ③ 打开实验箱,并挂载 / $ ifconfig eth0 192.168.1.55 up / $ ping 192.168.1.116 / $ mount-t nfs-o nolock 192.168.1.116:/home/shiyan/nfs /mnt/nfs / $ cd mnt/nfs /mnt/nfs $ ls ④ 执行客户端程序 /mnt/nfs $./serverjin 192.168.1.116 3456 接受到数据,实验成功 实验十二 WEB服务器程序 一. 实验目的 1.掌握httpd工具制作web服务器的基本流程 2.掌握实验设备的连接和调试 二. 实验内容 1.运行实验箱 2.通过路由器将实验箱和pc机连接 3.在pc机上运行浏览器,看是否运行网页服务器 三.实验设备 1.Pc机 2.嵌入式实验箱 3.Pc机操作系统 四.实验步骤 1.连接好实验箱,挂载nfs文件 / $ ifconfig eth0 192.168.1.55 / $ ping 192.168.1.116 / $ mount-t nfs-o nolock 192.168.1.116:/home/shiyan/nfs /mnt/nfs 3.进入nfs1/www文件夹查看可执行文件thttpd / $ cd mnt/nfs/nfs1 /mnt/nfs /nfs1 $ ls /mnt/nfs /nfs1/www $ ls 4.运行web服务器 /mnt/nfs /nfs1/www $./thttpd –c./thttpd.conf /mnt/nfs /nfs1/www $ cd thttpd/ /mnt/nfs /nfs1/www/thttpd $ ls 5.查看网络文件 /mnt/nfs /nfs1/www/thttpd $ cd html /mnt/nfs /nfs1/www/thttpd/html $ ls /mnt/nfs /nfs1/www/thttpd/html $ cat index.html 6.打开浏览器输入192.168.1.55,进入web页面 目录 实验一 跑马灯实验.........................................................................1 实验二 按键输入实验.....................................................................3 实验三 串口实验.............................................................................5 实验四 外部中断实验.....................................................................8 实验五 独立看门狗实验................................................................11 实验七 定时器中断实验................................................................13 实验十三 ADC实验........................................................................15 实验十五 DMA实验........................................................................17 实验十六 I2C实验........................................................................21 实验十七 SPI实验........................................................................24 实验二十一 红外遥控实验............................................................27 实验二十二 DS18B20实验.............................................................30 实验一 跑马灯实验 一.实验简介 我的第一个实验,跑马灯实验。 二.实验目的 掌握STM32开发环境,掌握从无到有的构建工程。 三.实验内容 熟悉MDK KEIL开发环境,构建基于固件库的工程,编写代码实现跑马灯工程。通过ISP下载代码到实验板,查看运行结果。使用JLINK下载代码到目标板,查看运行结果,使用JLINK在线调试。 四.实验设备 硬件部分:PC计算机(宿主机)、亮点STM32实验板、JLINK。软件部分:PC机WINDOWS系统、MDK KEIL软件、ISP软件。 五.实验步骤 1.熟悉MDK KEIL开发环境 2.熟悉串口编程软件ISP 3.查看固件库结构和文件 4.建立工程目录,复制库文件 5.建立和配置工程 6.编写代码 7.编译代码 8.使用ISP下载到实验板 9.测试运行结果 10.使用JLINK下载到实验板 11.单步调试 12.记录实验过程,撰写实验报告 六.实验结果及测试 源代码: 两个灯LED0与LED1实现交替闪烁的类跑马灯效果,每300ms闪烁一次。 七.实验总结 通过本次次实验我了解了STM32开发板的基本使用,初次接触这个开发板和MDK KEILC软件,对软件操作不太了解,通过这次实验了解并熟练地使用MDK KEIL软件,用这个软件来编程和完成一些功能的实现。作为 STM32 的入门第一个例子,详细介绍了STM32 的IO口操作,同时巩固了前面的学习,并进一步介绍了MDK的软件仿真功能。 实验二 按键输入实验 一.实验简介 在实验一的基础上,使用按键控制流水灯速度,及使用按键控制流水灯流水方向。 二.实验目的 熟练使用库函数操作GPIO,掌握中断配置和中断服务程序编写方法,掌握通过全局变量在中断服务程序和主程序间通信的方法。 三.实验内容 实现初始化GPIO,并配置中断,在中断服务程序中通过修改全局变量,达到控制流水灯速度及方向。 使用JLINK下载代码到目标板,查看运行结果,使用JLINK在线调试。 四.实验设备 硬件部分:PC计算机(宿主机)、亮点STM32实验板、JLINK、示波器。软件部分:PC机WINDOWS系统、MDK KEIL软件、ISP软件。 五.实验步骤 1在实验1代码的基础上,编写中断初始化代码 2在主程序中声明全局变量,用于和中断服务程序通信,编写完成主程序 3编写中断服务程序 4编译代码,使用JLINK下载到实验板 5.单步调试 6记录实验过程,撰写实验报告 六.实验结果及测试 源代码: 我们将通过MiniSTM32 板上载有的3个按钮,来控制板上的2个LED,其中KEY0控制LED0,按一次亮,再按一次,就灭。KEY1 控制LED1,效果同KEY0。KEY_2(KEY_UP),同时控制LED0 和LED1,按一次,他们的状态就翻转一次。 七.实验总结 通过本次实验,我学会了如何使用STM32 的IO 口作为输入用。TM32 的IO 口做输入使用的时候,是通过读取IDR 的内容来读取IO 口的状态的。这里需要注意的是 KEY0 和KEY1 是低电平有效的,而WK_UP 是高电平有效的,而且要确认WK_UP 按钮与DS18B20 的连接是否已经断开,要先断开,否则DS18B20 会干扰WK_UP按键!并且KEY0 和KEY1 连接在与JTAG 相关的IO 口上,所以在软件编写的时候要先禁用JTAG 功能,才能把这两个IO 口当成普通IO 口使用。 实验三 串口实验 一.实验简介 编写代码实现串口发送和接收,将通过串口发送来的数据回送回去。 二.实验目的 掌握STM32基本串口编程,进一步学习中断处理。 三.实验内容 编写主程序,初始化串口1,设置波特率为9600,无校验,数据位8位,停止位1位。编写中断服务程序代码实现将发送过来的数据回送。 四.实验设备 硬件部分:PC计算机(宿主机)、亮点STM32实验板、JLINK、示波器。 软件部分:PC机WINDOWS系统、MDK KEIL软件、ISP软件、串口调试助手。 五.实验步骤 1编写串口初始化代码 2编写中断服务程序代码 3编译代码,使用JLINK或ISP下载到实验板 4记录实验过程,撰写实验报告 六.实验结果及测试 源代码: 把代码下载到 MiniSTM32 开发板,可以看到板子上的LED0 开始闪烁,说明程序已经在跑了。接着我们打开串口调试助手,看到如下信息: 证明串口数据发送没问题。接着,我们在发送区输入上面的文字,输入完后按回车键。然后单击发送,可以得到如下结果: 七.实验总结 通过本次实验,我进一步了解了串口的使用,学会了通过串口发送和接收数据,将通过串口发送来的数据回送回去。该实验的硬件配置不同于前两个实验,串口 1 与USB 串口默认是分开的,并没有在PCB上连接在一起,需要通过跳线帽来连接一下。这里我们把P4 的RXD 和TXD 用跳线帽与P3 的PA9 和PA10 连接起来。 实验四 外部中断实验 一.实验简介 STM32 的 IO 口在本章第一节有详细介绍,而外部中断在第二章也有详细的阐述。这里我们将介绍如何将这两者结合起来,实现外部中断输入。 二.实验目的 进一步掌握串口编程,进一步学习外部中断编程,提高编程能力。 三.实验内容 初始化IO口的输入,开启复用时钟,设置IO与中断的映射关系,从而开启与IO口相对应的线上中断事件,设置触发条件。配置中断分组(NVIC),并使能中断,编写中断服务函数。 四.实验设备 硬件部分:PC计算机(宿主机)、亮点STM32实验板、JLINK、示波器。 软件部分:PC机WINDOWS系统、MDK KEIL软件、ISP软件、串口调试助手。 五.实验步骤 1.2.3.4.编写中断服务程序代码 使用ISP下载到实验板 测试运行结果 记录实验过程,撰写实验报告 六.实验结果及测试 源代码: 打开串口助手。 七.实验总结 首先需要将IO设置为中断输入口: 1)初始化 IO 口为输入。 2)开启 IO 口复用时钟,设置 IO 口与中断线的映射关系。 3)开启与该 IO口相对的线上中断/事件,设置触发条件。 4)配置中断分组(NVIC),并使能中断。 5)编写中断服务函数。 这一节,使用的是中断来检测按键,通过 WK_UP 按键实现按一次 LED0 和 LED 1 同时翻转,按 KEY0 翻转 LED0,按 KEY1 翻转 LED1。 试验中外部中断函数不能进入的原因分析 : 1)GPIO或者AFIO的时钟没有开启。2)GPIO和配置的中断线路不匹配。3)中断触发方式和实际不相符合。 4)中断处理函数用库函数时,写错,经常可能出现数字和字母之间没有下划线。5)外部中断是沿触发,有可能不能检测到沿,比如 中断线是低电平(浮空输入),触发是下降沿触发,可能会出现一直是低电平,高电平的时候是一样的情况,电平持续为高电平。 6)没有用软件中断来触发外部中断,调用函数EXTI_GenerateSWInterrupt;,因为软件中断先于边沿中断处理。 实验五 独立看门狗实验 一. 实验简介 独立看门狗(IWDG)由专用的低速时钟(LSI)驱动,即使主时钟发生故障它也仍然有效。窗口看门狗由从APB1时钟分频后得到的时钟驱动,通过可配置的时间窗口来检测应用程序非正常的过迟或过早的操作。 二.实验目的 通过编程,编写一个独立看门狗驱动程序 三.实验内容 启动 STM32 的独立看门狗,从而使能看门狗,在程序里面必须间隔一定时间喂狗,否则将导致程序复位。利用这一点,我们本章将通过一个 LED 灯来指示程序是否重启,来验证 STM32 的独立看门狗。 四.实验设备 硬件部分:PC计算机(宿主机)、亮点STM32实验板、JLINK。 软件部分:PC机WINDOWS系统、MDK KEIL软件、ISP软件、串口调试助手。 五.实验步骤 1.2.3.4.参考教材独立看门狗部分,编写独立看门狗驱动程序。建立和配置工程 编写代码 使用ISP下载到实验板 记录实验过程,撰写实验报告 六.实验结果及测试 源代码: 在配置看门狗后,看到LED0 不停的闪烁,如果WK_UP 按键按下,就喂狗,只要WK_UP 不停的按,看门狗就一直不会产生复位,保持LED0 的常亮,一旦超过看门狗定溢出时间(Tout)还没按,那么将会导致程序重启,这将导致LED0 熄灭一次。 七.实验总结 通过本次实验,我掌握了启动独立看门狗的步骤: 1)向 IWDG_KR 写入 0X5555。2)向 IWDG_KR 写入 0XAAAA。3)向 IWDG_KR 写入 0XCCCC。 通过上面 3个步骤,启动 STM32 的看门狗,从而使能看门狗,在程序里面就必须间隔一定时间喂狗,否则将导致程序复位。利用这一点,本章通过一个LED 灯来指示程序是否重启,来验证 STM32 的独立看门狗。在配置看门狗后,LED0 将常亮,如果 WK_UP 按键按下,就喂狗,只要 WK_UP 不停的按,看门狗就一直不会产生复位,保持 LED 0 的常亮,一旦超过看门狗溢出时间(Tout)还没按,那么将会导致程序重启,这将导致 LED 0 熄灭一次。 实验七 定时器中断实验 一. 实验简介 STM32 的定时器是一个通过可编程预分频器(PSC)驱动的 16 位自动装载计数器(CNT)构成。STM32 的通用定时器可以被用于:测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和 PWM)等。使用定时器预分频器和 RCC 时钟控制器预分频器,脉冲长度和波形周期可以在几微秒到几毫秒间调整。STM32 的每个通用定时器都是完全独立的,没有互相共享的任何资源。 二.实验目的 熟练掌握定时器中断,学会对定时器中断的编程操作。 三.实验内容 使用定时器产生中断,然后在中断服务函数里面翻转 LED1 上的电平,来指示定时器中断的产生,修改中断时间。 四.实验设备 硬件部分:PC计算机(宿主机)、亮点STM32实验板、JLINK。 软件部分:PC机WINDOWS系统、MDK KEIL软件、ISP软件、串口调试助手。 五.实验步骤 1.参考教材定时器中断部分,编写定时器中断的驱动程序。2.编写主程序 3.编译代码,使用JLINK或ISP下载到实验板 4.记录实验过程,撰写实验报告 六.实验结果及测试 源代码: 七.实验总结 通过本次实验,认识到时间中断来控制LED灯的闪烁,同时也可以将时间中断应用到控制其他的程序块。 以TIME3为例产生中断的步骤为 1)TIM3 时钟使能。 2)设置 TIM3_ARR 和 TIM3_PSC 的值。 3)设置 TIM3_DIER 允许更新中断。 4)允许 TIM3 工作。 5)TIM3 中断分组设置。6)编写中断服务函数。 在中断产生后,通过状态寄存器的值来判断此次产生的中断属于什么类型。然后执行相关的操作,我们这里使用的是更新(溢出)中断,所以在状态寄存器 SR 的最低位。在处理完中断之后应该向 TIM3_SR 的最低位写 0,来清除该中断标志。 实验十三 ADC实验 一.实验简介 通过DAC将STM32系统的数字量转换为模拟量。使用ADC将模拟量转换为数字量。 二.实验目的 掌握DAC和ADC编程。 三.实验内容 编写代码实现简单的DAC单次发送 编写代码实现ADC采集DAC发送的数据,并发送到串口 四.实验设备 硬件部分:PC计算机(宿主机)、亮点STM32实验板、JLINK。 软件部分:PC机WINDOWS系统、MDK KEIL软件、ISP软件、串口调试助手。 五.实验步骤 1编写主程序 2编译代码,使用JLINK或ISP下载到实验板,使用串口调试助手观察数据 3记录实验过程,撰写实验报告 六.实验结果及测试 源代码: 七.实验总结 本节将利用 STM32的 ADC1 通道 0 来采样外部电压值,并在串口调试助手中显示出来。步骤如下: 1)开启 PA 口时钟,设置 PA0 为模拟输入。 2)使能 ADC1 时钟,并设置分频因子。 3)设置 ADC1 的工作模式。 4)设置 ADC1 规则序列的相关信息。 5)开启 AD 转换器,并校准。 6)读取 ADC 值。 在上面的校准完成之后,ADC 就算准备好了。接下来我们要做的就是设置规则序列 0 里面的通道,然后启动 ADC 转换。在转换结束后,读取 ADC1_DR 里面的值。 通过以上几个步骤的设置,可以正常的使用 STM32 的 ADC1 来执行 AD 转换操作。 通过本次实验的学习,我们了解了STM32 ADC的使用,但这仅仅是STM32强大的ADC 功能的一小点应用。STM32 的ADC 在很多地方都可以用到,其ADC 的DMA 功能是很不错的,实验十五 DMA实验 一. 实验简介 直接存储器存取(DMA)用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU干预,数据可以通过DMA快速地移动,这就节省了CPU的资源来做其他操作。 二.实验目的 熟练掌握DMA编程,学会对EPC02的读写操作,学习双缓冲兵乓操作,理解互斥资源。提高编程能力。 三.实验内容 利用外部按键KEY0 来控制DMA 的传送,每按一次KEY0,DMA 就传送一次数据 到USART1,然后在串口调试助手观察进度等信息。LED0 还是用来做为程序运行的指示灯。 这里我们使用到的硬件资源如下: 1)按键KEY0。2)指示灯LED0。 3)使用串口调试助手观察数据 四.实验设备 硬件部分:PC计算机(宿主机)、亮点STM32实验板、JLINK。 软件部分:PC机WINDOWS系统、MDK KEIL软件、ISP软件、网络调试助手。 五.实验步骤 1编写主程序 2编译代码,使用JLINK或ISP下载到实验板,使用串口调试助手观察数据 3记录实验过程,撰写实验报告 六.实验结果及测试 源代码: 伴随 LED0 的不停闪烁,提示程序在运行。我们打开串口调试助手,然后按KEY0,可以看到串口显示如下内容: 七.实验总结 本节利用 STM32 的 DMA 来实现串口数据传送,DMA通道的配置需要: 1)设置外设地址。 2)设置存储器地址。 3)设置传输数据量。 4)设置通道 4 的配置信息。 5)使能 DMA1 通道 4,启动传输。 通过以上 5 步设置,我们就可以启动一次 USART1 的 DMA 传输了。 DMA控制器对DMA请求判别优先级及屏蔽,向总线裁决逻辑提出总线请求。当CPU执行完当前总线周期即可释放总线控制权。此时,总线裁决逻辑输出总线应答,表示DMA已经响应,通过DMA控制器通知I/O接口开始DMA传输。 DMA控制器获得总线控制权后,CPU即刻挂起或只执行内部操作,由DMA控制器输出读写命令,直接控制RAM与I/O接口进行DMA传输。 在DMA控制器的控制下,在存储器和外部设备之间直接进行数据传送,在传送过中不需要中央处理器的参与。开始时需提供要传送的数据的起始位置和数据长度。 当完成规定的成批数据传送后,DMA控制器即释放总线控制权,并向I/O接口发出结束信号。当I/O接口收到结束信号后,一方面停 止I/O设备的工作,另一方面向CPU提出中断请求,使CPU从不介入的状态解脱,并执行一段检查本次DMA传输操作正确性的代码。最后,带着本次操作结果及状态继续执行原来的程序。 由此可见,DMA传输方式无需CPU直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为RAM与I/O设备开辟一条直接传送数据的通路,使CPU的效率大为提高。 实验十六 I2C实验 一.实验简介 编程实现对使用I2C接口的EPC02芯片进行写和读操作。 二.实验目的 熟练掌握I2C编程,学会对EPC02的读写操作。 三.实验内容 编写I2C驱动程序,使用驱动程序初始化EPC02,判断设备正确性。 写256个0x5A到EPC02,读出并发送给串口,通过串口调试助手判别是否读到的都是0x5A.四.实验设备 硬件部分:PC计算机(宿主机)、亮点STM32实验板、JLINK。 软件部分:PC机WINDOWS系统、MDK KEIL软件、ISP软件、串口调试助手。 五.实验步骤 1参考教材I2C部分,编写I2C驱动程序。2编写主程序 3编译代码,使用JLINK或ISP下载到实验板 4记录实验过程,撰写实验报告 六.实验结果及测试 伴随 LED0 的不停闪烁,提示程序在运行。我们先按下KEY0,可以看到如下所示的内容,证明数据已经被写入到24C02了。 接着我们按KEY2,可以看我们刚刚写入的数据被显示出来了,如下图所示: 源代码: 七.实验总结 IIC是由数据线 SDA 和时钟 SCL 构成的串行总线,可发送和接收数据。在 CPU 与被控 IC 之间、IC 与 IC 之间进行双向传送,高速 IIC 总线一般可达 400kbps 以上。 IIC总线在传送数据过程中共有三种类型信号,它们分别是:开始信号、结束信号和应答信号。这些信号中,起始信号是必需的,结束信号和应答信号,都可以不要。程序在开机的时候会检测 24C02 是否存在,如果不存在则会在TFTLCD 模块上显示错误信息,同时LED0 慢闪。大家可以通过跳线帽把PC11 和PC12 短接就可以看到报错了。通过本次实验,我掌握了如何使用IIC写入与读出数据,学习了编写I2C驱动程序,使用驱动程序初始化EPC02,判断设备正确性,以及如何在助手上显示。 实验十七 SPI实验 一.实验简介 编程实现对SPI接口的W25Q64进行读写操作。 二.实验目的 熟练掌握SPI编程,学会对的W25Q64读写操作。 三.实验内容 1.2.3.4.5.编写SPI驱动程序 初始化SPI接口 读取SPIFLASH的ID,如果正确继续,否则报错 向SPIFALSH地址0x12AB00开始写一串字符,再读出比较判断是否与写入的一致 向SPIFALSH地址0x12AB00开始写连续256个字节的0x5A,然后读出并发送给串口,通过串口调试助手判别是否读到的都是0x5A.四.实验设备 硬件部分:PC计算机(宿主机)、亮点STM32实验板、JLINK。 软件部分:PC机WINDOWS系统、MDK KEIL软件、ISP软件、串口调试助手。 五.实验步骤 1参考SPI及SPI FLASH部分,编写SPI及SPI FLASH驱动程序(可参考书上代码)。2编写主程序 3编译代码,使用JLINK或ISP下载到实验板 4记录实验过程,撰写实验报告 六.实验结果及测试 源代码: 伴随 LED0 的不停闪烁,提示程序在运行。我们先按下KEY0,可以看到如图13.17.4.2 所示的内容,证明数据已经被写入到W25X16了。 接着我们按KEY2,可以看我们刚刚写入的数据被显示出来了,如下图所示: 七.实验总结 SPI 接口主要应用在EEPROM,FLASH,实时时钟,AD 转换器,还有数字信号处理器和数字信号解码器之间。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为 PCB 的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议,STM32 也有 SPI 接口。 SPI 的设置步骤: 1)配置相关引脚的复用功能,使能 SPI时钟。 2)设置 SPI 工作模式。 3)使能 SPI。 程序在开机的时候会检测 W25X16 是否存在,如果不存在则会在TFTLCD 模块上显示错误信息,同时LED0 慢闪。大家可以通过跳线帽把PA5 和PA6 短接就可以看到报错了。通过本实验,我掌握了编写SPI程序写入和读取FLASH的方法,掌握了对学会对的W25Q64读写操作。对STM32开发板有了进一步的了解。 实验二十一 红外遥控实验 一. 实验简介 编程实现通过在 ALIENTEK MiniSTM32 开发板上实现红外遥控器的控制。 二.实验目的 掌握编程实现红外遥控控制开发板的方法。 三.实验内容 1.编写红外遥控驱动程序 2.编写红外遥控程序代码 3.使用红外遥控控制开发板 四.实验设备 硬件部分:PC计算机(宿主机)、亮点STM32实验板、JLINK。软件部分:PC机WINDOWS系统、MDK KEIL软件、ISP软件。 五.实验步骤 4.编写红外遥控驱动程序 5.编写红外遥控程序代码 6.编译代码,使用JLINK或ISP下载到实验板 7.记录实验过程,撰写实验报告 六.实验结果及测试 源代码: 使用串口调试助手观察数据 七.实验总结 红外遥控是一种无线、非接触控制技术,具有抗干扰能力强,信息传输可靠,功耗低,成本低,易实现等显著优点,被诸多电子设备特别是家用电器广泛采用,并越来越多的应用到计算机系统中。 通过本节实验,我学习到了如何编程使用红外遥控控制,在本程序中只是简单地输出一个数值,在以后的应用中可以实现更强大的功能,比如用红外远程输入控制开发板进行一些操作。对STM32有了进一步的认识。 实验二十二 DS18B20实验 一. 实验简介 一. 在ALIENTEK MiniSTM32 开发板上,通过 DS18B20 来读取环境温度值。 二.实验目的 巩固SPI编程。掌握使用感应器获取环境温度的方法。 三.实验内容 1.复位脉冲和应答脉冲 2.写时序 3.读时序 四.实验设备 硬件部分:PC计算机(宿主机)、亮点STM32实验板、JLINK。软件部分:PC机WINDOWS系统、MDK KEIL软件、ISP软件。 五.实验步骤 1.2.3.4.参考教材DS18B20编程部分,编写DS18B20驱动程序 编写主程序 编译代码,使用JLINK或ISP下载到实验板 记录实验过程,撰写实验报告 六.实验结果及测试 源代码: 使用串口调试助手观察数据: 七.实验总结 DS18B20 是由 DALLAS 半导体公司推出的一种的“一线总线”接口的温度传感器。与传统的热敏电阻等测温元件相比,它是一种新型的体积小、适用电压宽、与微处理器接口简单的数字化温度传感器。 通过本次实验,我认识到STM32的强大,在开发板上可以添加其他感应器从而实现更强大的功能。添加了DS18B20后的开发板可以感应外界的温度,通过公式计算显示出来。 嵌入式系统及应用课 程设计报告 姓名:陈宥祎 班级:14级计算机01班 学号:1255010116 指导老师:黄卫红 按键输入实验 一.实验简介 在实验一的基础上,使用按键控制流水灯速度,及使用按键控制流水灯流水方向。 二.实验目的 熟练使用库函数操作GPIO,掌握中断配置和中断服务程序编写方法,掌握通过全局变量在中断服务程序和主程序间通信的方法。 三.实验内容 实现初始化GPIO,并配置中断,在中断服务程序中通过修改全局变量,达到控制流水灯速度及方向。 使用JLINK下载代码到目标板,查看运行结果,使用JLINK在线调试。 四.实验设备 硬件部分:PC计算机(宿主机)、亮点STM32实验板、JLINK、示波器。软件部分:PC机WINDOWS系统、MDK KEIL软件、ISP软件。 五.实验步骤 1在实验1代码的基础上,编写中断初始化代码 2在主程序中声明全局变量,用于和中断服务程序通信,编写完成主程序 3编写中断服务程序 4编译代码,使用JLINK下载到实验板 5.单步调试 6记录实验过程,撰写实验报告 六.实验结果及测试 源代码: 我们将通过MiniSTM32 板上载有的3个按钮,来控制板上的2个LED,其中KEY0控制LED0,按一次亮,再按一次,就灭。KEY1 控制LED1,效果同KEY0。KEY_2(KEY_UP),同时控制LED0 和LED1,按一次,他们的状态就翻转一次。 七.实验总结 通过本次实验,我学会了如何使用STM32 的IO 口作为输入用。TM32 的IO 口做输入使用的时候,是通过读取IDR 的内容来读取IO 口的状态的。这里需要注意的是 KEY0 和KEY1 是低电平有效的,而WK_UP 是高电平有效的,而且要确认WK_UP 按钮与DS18B20 的连接是否已经断开,要先断开,否则DS18B20 会干扰WK_UP按键!并且KEY0 和KEY1 连接在与JTAG 相关的IO 口上,所以在软件编写的时候要先禁用JTAG 功能,才能把这两个IO 口当成普通IO 口使用。 串口通信 一.实验简介 编写代码实现串口发送和接收,将通过串口发送来的数据回送回去。 二.实验目的 掌握STM32基本串口编程,进一步学习中断处理。 三.实验内容 编写主程序,初始化串口1,设置波特率为9600,无校验,数据位8位,停止位1位。编写中断服务程序代码实现将发送过来的数据回送。 四.实验设备 硬件部分:PC计算机(宿主机)、亮点STM32实验板、JLINK、示波器。 软件部分:PC机WINDOWS系统、MDK KEIL软件、ISP软件、串口调试助手。 五.实验步骤 1编写串口初始化代码 2编写中断服务程序代码 3编译代码,使用JLINK或ISP下载到实验板 4记录实验过程,撰写实验报告 六.实验结果及测试 源代码: 把代码下载到 MiniSTM32 开发板,可以看到板子上的LED0 开始闪烁,说明程序已经在跑了。接着我们打开串口调试助手,看到如下信息: 证明串口数据发送没问题。接着,我们在发送区输入上面的文字,输入完后按回车键。然后单击发送,可以得到如下结果: 七.实验总结 通过本次实验,我进一步了解了串口的使用,学会了通过串口发送和接收数据,将通过串 口发送来的数据回送回去。该实验的硬件配置不同于前两个实验,串口 1 与USB 串口默认是分开的,并没有在PCB上连接在一起,需要通过跳线帽来连接一下。这里我们把P4 的RXD 和TXD 用跳线帽与P3 的PA9 和PA10 连接起来。 外部中断 一.实验简介 STM32 的 IO 口在本章第一节有详细介绍,而外部中断在第二章也有详细的阐述。这里我们将介绍如何将这两者结合起来,实现外部中断输入。 二.实验目的 进一步掌握串口编程,进一步学习外部中断编程,提高编程能力。 三.实验内容 初始化IO口的输入,开启复用时钟,设置IO与中断的映射关系,从而开启与IO口相对应的线上中断事件,设置触发条件。配置中断分组(NVIC),并使能中断,编写中断服务函数。 四.实验设备 硬件部分:PC计算机(宿主机)、亮点STM32实验板、JLINK、示波器。 软件部分:PC机WINDOWS系统、MDK KEIL软件、ISP软件、串口调试助手。 五.实验步骤 1.2.3.4.编写中断服务程序代码 使用ISP下载到实验板 测试运行结果 记录实验过程,撰写实验报告 六.实验结果及测试 源代码: 打开串口助手。 七.实验总结 首先需要将IO设置为中断输入口: 1)初始化 IO 口为输入。 2)开启 IO 口复用时钟,设置 IO 口与中断线的映射关系。 3)开启与该 IO口相对的线上中断/事件,设置触发条件。 4)配置中断分组(NVIC),并使能中断。 5)编写中断服务函数。 这一节,使用的是中断来检测按键,通过 WK_UP 按键实现按一次 LED0 和 LED 1 同时翻转,按 KEY0 翻转 LED0,按 KEY1 翻转 LED1。试验中外部中断函数不能进入的原因分析 : 1)GPIO或者AFIO的时钟没有开启。2)GPIO和配置的中断线路不匹配。3)中断触发方式和实际不相符合。 4)中断处理函数用库函数时,写错,经常可能出现数字和字母之间没有下划线。5)外部中断是沿触发,有可能不能检测到沿,比如 中断线是低电平(浮空输入),触发是下降沿触发,可能会出现一直是低电平,高电平的时候是一样的情况,电平持续为高电平。 6)没有用软件中断来触发外部中断,调用函数EXTI_GenerateSWInterrupt;,因为软件中断先于边沿中断处理。 独立看门狗实验 一. 实验简介 独立看门狗(IWDG)由专用的低速时钟(LSI)驱动,即使主时钟发生故障它也仍然有效。窗口看门狗由从APB1时钟分频后得到的时钟驱动,通过可配置的时间窗口来检测应用程序非正常的过迟或过早的操作。 二.实验目的 通过编程,编写一个独立看门狗驱动程序 三.实验内容 启动 STM32 的独立看门狗,从而使能看门狗,在程序里面必须间隔一定时间喂狗,否则将导致程序复位。利用这一点,我们本章将通过一个 LED 灯来指示程序是否重启,来验证 STM32 的独立看门狗。 四.实验设备 硬件部分:PC计算机(宿主机)、亮点STM32实验板、JLINK。 软件部分:PC机WINDOWS系统、MDK KEIL软件、ISP软件、串口调试助手。 五.实验步骤 1.2.3.4.参考教材独立看门狗部分,编写独立看门狗驱动程序。建立和配置工程 编写代码 使用ISP下载到实验板 记录实验过程,撰写实验报告 六.实验结果及测试 源代码: 在配置看门狗后,看到LED0 不停的闪烁,如果WK_UP 按键按下,就喂狗,只要WK_UP 不停的按,看门狗就一直不会产生复位,保持LED0 的常亮,一旦超过看门狗定溢出时间(Tout)还没按,那么将会导致程序重启,这将导致LED0 熄灭一次。 七.实验总结 通过本次实验,我掌握了启动独立看门狗的步骤: 1)向 IWDG_KR 写入 0X5555。2)向 IWDG_KR 写入 0XAAAA。3)向 IWDG_KR 写入 0XCCCC。 通过上面 3个步骤,启动 STM32 的看门狗,从而使能看门狗,在程序里面就必须间隔一定时间喂狗,否则将导致程序复位。利用这一点,本章通过一个LED 灯来指示程序是否重启,来验证 STM32 的独立看门狗。在配置看门狗后,LED0 将常亮,如果 WK_UP 按键按下,就喂狗,只要 WK_UP 不停的按,看门狗就一直不会产生复位,保持 LED 0 的常亮,一旦超过看门狗溢出时间(Tout)还没按,那么将会导致程序重启,这将导致 LED 0 熄灭一次。 西安邮电大学 嵌入式处理器及应用实验报告书 学院名称学生姓名专业名称班 级 : : : : 实验一 ADS 1.2 集成开发环境练习 一、实验目的: 了解ADS 1.2 集成开发环境的使用方法。 二、实验内容: 1.建立一个新的工程。 2.建立一个C源文件,并添加到工程中。3.设置文本编辑器支持中文。4.编译链接工程。5.调试工程。 三、实验步骤: 1.启动ADS 1.2 IDE集成开发环境,选择File—New,使用ARM Executable Image工程模板建立一个工程,工程名称为ADS。 2.选择File—New建立一个新的文件TEST1.S,设置直接添加到项目中,输入程序代码。3.由于ADS安装后默认字体是Courier New,对于中文支持不完善,因此建议修改字体。选择Edit—Perferences,在Font选项设置字体为Fixedsys,Script为CHINESE_GB2312。建议在Tab Inserts Spaces前打勾,使Tab键插入的是多个空格。 4.选择Edit—DebugRel Settings,在DebugRel Settings对话框的左边选择ARM Linker项,然后在Output页设置连接地址ROBase 为0x40000000,RW Base 为0x40003000,在Options页设置调试入口地址Image entry point 为 0x40000000。5.选择Project—Make,将编译链接整个工程。 6.选择Project—Debug,或单击快捷键F5,IDE环境就会启动AXD调试软件。 四、程序清单: AREA Example1,CODE,READONLY ;声明代码段Example1 ENTRY ;标识程序入口 CODE32 ;声明32 位ARM 指令 START MOV R0,#15 ;设置参数 MOV R1,#8 ADDS R0,R0,R1 ;R0 = R0 + R1 B START END 五、心得体会: 通过本次实验,我熟悉了ADS 1.2 集成开发环境,学会了怎样建立工程,在工程里面建立文件和进行最基本的运行操作。我感触最深的是每次软件的开始使用是最关键的,想要掌握一个软件的使用必须进行多次的练习,多练几遍自然而然的会熟练的操作。 实验二 存储器访问指令练习实验 一、实验目的: 1.了解ADS 1.2 集成开发环境及ARMulator软件仿真。 2.掌握ARM7TDMI汇编指令的用法,并能编写简单的汇编程序。3.掌握指令的条件执行以及使用LDR/STR指令完成存储器的访问。 二、实验内容: 1.使用LDR指令读取0x40003100上的数据,将数据加1,若结果小于10,则使用STR指令把结果回写原地址;若结果大于或等于10,则把0写回原地址。 2.使用ADS 1.2软件仿真,单步、全速运行程序,设置断点,打开寄存器窗口(Processor Registers)监视R0和R1的值,打开存储器观察窗口(Memory)监视0x40003100上的值。 三、实验步骤: 1.启动ADS 1.2,使用ARM Executable Image工程模板建立一个工程Instruction2。2.建立汇编源文件TEST2.S,编写实验程序,然后添加到工程中。 3.设置工程链接地址ROBase 为0x40000000,RW Base 为0x40003000。设置调试入口地址Image entry point 为 0x40000000。 4.编译链接工程,选择Project —Debug,启动AXD进行软件仿真调试。 5.打开寄存器窗口(Processor Registers),选择Current 项监视R0和R1的值。打开存储器观察窗口(Memory)设置观察地址为0x40003100,显示方式Size为32Bit,监视0x40003100地址上的值。 四、程序清单: COUNT EQU 0x40003100 ;定义一个变量,地址为0x40003100 AREA Example2,CODE,READONLY;声明代码段Example2 ENTRY ;标识程序入口 CODE32 ;声明32 位ARM 指令 START LDR R1,=COUNT ;R1 <= COUNT MOV R0,#0 ;R0 <= 0 STR R0,[R1] ;[R1] <= R0,即设置COUNT 为0 LOOP LDR R1,=COUNT LDR R0,[R1] ;R0 <= [R1] ADD R0,R0,#1 ;R0 <= R0 + 1 CMP R0,#10 ;R0 与 10 比较,影响条件码标志 MOVHS R0,#0 ;若R0 大于等于 10,则此指令执行,R0 <= 0 STR R0,[R1] ;[R1] <= R0,即保存COUNT B LOOP END 五、心得体会:通过本次实验,让我更深一步的了解了ADS 1.2 集成开发环境及ARMulator软件仿真。通过对程序的解读,我掌握一些汇编指令的写法,同时也提高了我的读程序的能力。本次实验中我遇到了一个问题,在工程里加载文件的时候,没注意文件的后缀应为“。S”,结果造成文件加载失败。 实验三 数据处理指令练习实验 一、实验目的: 1.掌握ARM数据处理指令的使用方法。2.了解ARM指令灵活的第2个操作数。 二、实验内容: 1.使用MOV和MVN指令访问ARM通用寄存器。 2.使用ADD、SUB、AND、ORR、CMP和TST等指令完成数据加减运算及逻辑运算。 三、实验步骤: 1)启动ADS1.2,使用ARM Executable Image 工程模板建立一个工程Instruction3。2)建立汇编源文件TEST3.S ,编写实验程序,然后添加到工程中。 3)设置工程链接地址RO Base为0x40000000,RW Base为0x40003000。设置调试入口地址Image entry point 为 0x40000000。 4)编译链接工程,选择Project —Debug,启动AXD进行软件仿真调试。5)打开寄存器窗口(Processor Registers),选择Current 项监视各寄存器的值。6)单步运行程序,观察寄存器值的变化。 四、程序清单: X EQU ;定义X 的值为11 Y EQU ;定义Y 的值为8 BIT23 EQU (1<<23) ;定义BIT23 的值为0x00800000 AREA Example3,CODE,READONLY ;声明代码段Example3 ENTRY ;标识程序入口 CODE32 ;声明32 位ARM 指令 START ;使用MOV、ADD 指令实现:R8 = R3 = X + Y MOV R0,#X ;R0 <= X,X 的值必须是8 位图数据 MOV R1,#Y ;R1 <= Y,Y 的值必须是8 位图数据 ADD R3,R0,R1 ;即是R3 = X + Y MOV R8,R3 ;R8 <= R3 ;使用MOV、MVN、SUB 指令实现:R5 = 0x5FFFFFF8y; ; break; ; case 7: x = key * y; ; break; ; default: x = 168; SWITCH CASE_0 CASE_2 CASE_3 CASE_5 CASE_7 ; break;;};设x 为R0,y 为R1,key 为R2(x、y、key 均为无符号整数)MOV R1,#3 ;初始化y 的值 MOV R2,#2 ;初始化key 的值 AND R2,R2,#0x0F ;switch(key&0x0F) CMP R2,#0 ;case 0: CMPNE R2,#2 ;case 2: MPNE R2,#3 ;case 3: BNE CASE_5 ADD R0,R2,R1 ; x = key + y B SWITCH_END ; break CMP R2,#5 ;case 5: BNE CASE_7 SUB R0,R2,R1 ; x = key1)*4 SvcStackSpace +(SVC_STACK_LEGTH1)*4 FiqStackSpace +(FIQ_STACK_LEGTH1)*4 UndtStackSpace +(UND_STACK_LEGTH-1)*4 ;分配堆栈空间 AREA MyStacks, DATA, NOINIT, ALIGN=2 UsrStackSpace SPACE USR_STACK_LEGTH * 4 ;用户(系统)模式堆栈空间 SvcStackSpace SPACE SVC_STACK_LEGTH * 4 ;管理模式堆栈空间 IrqStackSpace SPACE IRQ_STACK_LEGTH * 4 ;中断模式堆栈空间 FiqStackSpace SPACE FIQ_STACK_LEGTH * 4 ;快速中断模式堆栈空间 AbtStackSpace SPACE ABT_STACK_LEGTH * 4 ;中止义模式堆栈空间 UndtStackSpace SPACE UND_STACK_LEGTH * 4 ;未定义模式堆栈 END 五、心得体会:通过本次实验,我较好的掌握了如何使用MRS/MSR指令实现ARM微控制器工作模式的切换。较好的了解了在各个工作模式下的寄存器。 实验六 C语言程序实验 一、实验目的: 通过实验了解使用ADS 1.2编写C语言程序,并进行调试。 二、实验内容: 编写一个汇编程序文件和一个C程序文件。汇编程序的功能是初始化堆栈指针和初始化C程序的运行环境,然后跳转到C程序运行,这就是一个简单的启动程序。C程序使用加法运算来计算1+2+3+…+(N-1)+N的值(N为0时,结果为0;N为1时,结果为1)。 三、实验步骤: 1.启动ADS1.2,使用ARM Executable Image 工程模板建立一个工程ProgramC。2.建立汇编源文件Startup.s和Test.c,编写实验程序,然后添加到工程中。 3.设置工程链接地址RO Base为0x40000000,RW Base为0x40003000。设置调试入口地址Image entry point 为 0x40000000。 4.设置位于开始位置的起始代码段:选择Edit—DebugRel Settings,在DebugRel Settings对话框的左边选择ARM Linker项,然后在Layout页设置Object/Symbol为Startup.o,Section为Start。 5.编译链接工程,选择Project—Debug,启动AXD进行软件仿真调试。6.在Startup.s的“B Main”处设置断点,然后全速运行程序。 7.程序在断点处停止。单步运行程序,判断程序是否跳转到C程序中运行。 选择Processor Views—Variables打开变量观察窗口,观察全局变量的值,然后单步/全速运行程序,判断程序的运算结果是否正确。 四、程序清单: #define uint8 unsigned char #define uint32 unsigned int #define N uint32 sum; // 使用加法运算来计算 1+2+3+...+(N-1)+N 的值。(N>0) void Main(void) { uint32 i; sum = 0; for(i=0;i<=N;i++) { sum += i; } while(1); } 程序清单3.9 简单的起动代码 ;起动文件。初始化 C 程序的运行环境,然后进入C 程序代码。 IMPORT |Image$$RO$$Limit| IMPORT |Image$$RW$$Base| IMPORT |Image$$ZI$$Base| IMPORT |Image$$ZI$$Limit| IMPORT Main ;声明C 程序中的Main()函数 AREA Start,CODE,READONLY ;声明代码段Start ENTRY ;标识程序入口 CODE32 ;声明32 位ARM 指令 Reset LDR SP,=0x40003F00 ;初始化C 程序的运行环境 LDR R0,=|Image$$RO$$Limit| LDR R1,=|Image$$RW$$Base| LDR R3,=|Image$$ZI$$Base| CMP R0,R1 BEQ LOOP1 LOOP0 CMP R1,R3 LDRCC R2,[R0],#4 STRCC R2,[R1],#4 BCC LOOP0 LOOP1 LDR R1,=|Image$$ZI$$Limit| MOV R2,#0 LOOP2 CMP R3,R1 STRCC R2,[R3],#4 BCC LOOP2 B Main ;跳转到 C 程序代码Main()函数 END 五、心得体会:通过本次实验,我学会并掌握使用ADS 1.2编写C语言程序,并进行调试。这次实验不同于前几次,必须在一个工程里面同时加载两个文件,分别是“。c”和“.s”文件。 实验一 ARM汇编语言程序设计 一、实验目的 1.了解IAR Embedded Workbench 集成开发环境 2.掌握ARM汇编指令程序的设计及调试 二、实验设备 1.PC操作系统WIN98或WIN2000或WINXP,ADSI.2集成开发环境,仿真驱动程序 三、实验内容 1.熟悉IAR Embedded Workbench 集成开发环境 2.理解下列程序,新建工程,加入下面的程序,并观察实验结果,解释程序实现的功能 分析:该程序实现的功能是程序功能:Y = A*B+C*D+E*F 程序代码: AREA Examl, CODE,READONLY;定义一个代码段 ENTRY ;程序入口 MOV R0,#0;设置R0寄存器的值为0 MOV R8,#0;设置R8寄存器的值为0 ADR R2,N;将R2寄存器的值设为数据域N的地址 LDR R1,[R2];将以R2的值为地址的数据读入R1 MOV R2,#0;设置R2的值为0 ADR R3,C;将R3寄存器的值设为数据域C的地址 ADR R5,X;将R5寄存器的值设为数据域X的地址 LOOP LDR R4,[R3,R8];将R3+R8的数据读入R4 LDR R6,[R5,R8];将R5+R8的数据读入R6 MUL R9,R4,R6;R9 = R4*R6 ADD R2,R2,R9;R2 = R2+R9 ADD R8,R8,#4;R8 = R8+4 ADD R0,R0,#1;R0 = R0+1 CMP R0,R1;比较R0和R1的值 BLT LOOP;R0 执行结果如下: 3.实现1+2+3+4+····+100,求的值,并保存在地址0x90018的地址里面 程序代码: MOV R0,#100;设置R0寄存器的值为100 LDR R2,=0X90018;设置R2寄存器指向地址0x90018 MOV R1,#0;设置R1的值为0 MOV R3,#0;设置R3的值为0 LOOP ADD R3,R3,R0;R3 = R3+R0 SUB R0,R0,#1;R0 = R0-1 CMP R0,R1;将R0和R1的值比较 BNE LOOP;不相等的话继续执行循环 STR R3,[R2];将R3的值装入到R2指向的地址块中。END 程序执行结果:程序执行完在0x90018内存入的数据是0x13ba即5050 实验二 ARM汇编语言程序设计 一、实验目的 1.了解ARM汇编语言的基本框架,学会使用ARM的汇编语言编程; 2.掌握ARM汇编指令中的堆栈指令的操作,以及存储器的装载指令操作。 二、实验设备 1.PC操作系统WIN98或WIN2000或WINXP,ADS1.2.集成开发环境,仿真器驱动程序。 三、实验内容 1.理解下列程序,新建工程,加入下面的程序,并观察实验结果 程序代码: x EQU 15;定义常量x=15 y EQU 61;定义常量y=61 stack_top EQU 0X1000;定义堆栈栈顶地址为0x1000 ENTRY;程序入口处 MOV sp,#stack_top;将堆栈指针指向栈顶 MOV r0,#x;将x的值放入r0 STR r0,[sp];将r0的值压入堆栈 MOV r0,#y;将y的值放入r0 LDR r1,[sp];将x的值放入r1 ADD r0,r0,r1;r0 = r0+r1 STR r0,[sp];将r0的值装入堆栈 Stop;B stop;程序结果为:r1 = x+y = 0x6D 2.编写程序循环R4~R11进行累加8次赋值,R4~R11初始值是1~8,每次操作后把R4~R11的内容放到SP栈中,SP初始设置为0x800,最后把R4~R11用LDMFD指令清空为0 程序代码如下: X EQU 1;定义常量x = 1 stack_top EQU 0X800;定义栈顶地址 ENTRY;MOV SP,#stack_top;将栈顶地址指向0x800 MOV R4,#1;设置R4 = 1 MOV R5,#2;设置R5 = 2 MOV R6,#3;设置R6 = 3 MOV R7,#4;设置R7 = 4 MOV R8,#5;设置R8 = 5 MOV R9,#6;设置R9 = 6 MOV R10,#7;设置R10 = 7 MOV R11,#8;设置R11 = 8 LOOP ADD R4,R4,#x;R4累加1 ADD R5,R5,#x;R5累加1 ADD R6,R6,#x;R6累加1 ADD R7,R7,#x;R7累加1 ADD R8,R8,#x;R8累加1 ADD R9,R9,#x;R9累加1 ADD R10,R10,#x;R10累加1 ADD R11,R11,#x;R11累加1 STMIA SP!,{R4-R11};将R4-R11的值压入堆栈 CMP R4,#9;比较R4和9的大小 BLT LOOP;R4 < 9继续执行循环 LDMFD SP!,{R4-R11};将R4-R11清零 END;实验结果:主要实现将数据2-9,3-10,4-11……9-16压入堆栈(初始地址是0x800处开始),最后将R4-R11全部清零。 3.更改实验中1中的X,Y的值,观察期结果 程序代码: x EQU 20 y EQU 120 stack_top EQU 0X1000 ENTRY MOV sp,#stack_top MOV r0,#x STR r0,[sp] MOV r0,#y LDR r1,[sp] ADD r0,r0,r1 STR r0,[sp] Stop B Stop END 程序结果为:r0 = x+y = 140 = 0X8C 实验三 ARM汇编语言程序设计 一、实验目的 1.了解ARM汇编语言的基本框架,学会使用ARM的汇编语言编程 2.掌握ARM汇编的存储器加载/存储指令,及if条件、循环、循环及循环的汇编实现 二、实验设备 1.PC操作系统WIN98或WIN2000或WINXP,ADS1.2集成开发环境,仿真器驱动程序 三、实验内容 1.理解下列程序,新建工程,加入下面的程序,并观察实验结果 程序代码: Num EQU 20;定义常量Num = 20 START;LDR r0,=src;将src数据块的开始地址存入r0中 LDR r1,=dst;将dst数据块的开始地址存入r1中 MOV r2,#Num;设置r2的值为20 MOV sp,#0x400;堆栈指针sp指向0x400 blockcopy;MOVS r3,r2,LSR #3;将r2左移3位移入r3并且影响标志位 BEQ copywords;结果为0的话跳转到copywords STMFD SP!,{r4-r11};将r4-r11的值入栈 octcopy;LDMIA r0!,{r4-r11};将src的前8个字数据存入让r4-r11 STMIA r1!,{r4-r11};将r4-r11中的数据放入dst数据块中 SUBS r3,r3,#1;r3 = r3-1 BNE octcopy;结果不为0跳转到octcopy LDMFD SP!,{R4-R11};恢复原来的r4-r11 copywords;ANDS r2,r2,#7;r2 = r2&7 BEQ stop;结果为0跳转到stop wordcopy;LDR r3,[r0],#4;将r0指向的字数据放入r3中,r0 = r0+4 STR r3,[r1],#4;将r3中的数据存入到dst数据块中,r1 = r1+4 SUBS r2,r2,#1;r2 = r2-1 BNE wordcopy;不为0跳转到wordcopy处 stop;B stop;src DCD 1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,1,2,3,4;dst DCD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0;END;程序结果:将src的数据全部存入到dst中 2.新建工程,并自行编写程序,分别使用LDR,STR,LDMIA,STMIA操作,实现对某段连续存储单元写入数据,并观察结果 程序代码: MOV R4,#1;设置r4 = 1; MOV R5,#2;设置r5 = 1; MOV R6,#3;设置r4 = 1; LDR R0,=dst;R0保存dst的首地址 STR R4,[R0];将r4的值装入r0执行的内存中 STR R5,[R0,#4];将r5的值装入r0+4执行的内存中 STR R6,[R0,#8];将r6的值装入r0+8执行的内存中 LDR R7,=src;R0保存src的首地址 LDMIA R7,{R8-R10};将r7执行的地址的数据读入r8=r10 LDR R3,=N;r3保存N的首地址 STMIA R3!,{R8-R10};将r8-r10装入r3指向的内存 N DCD 0,0,0 src DCD 1,2,3 dst DCD 0,0,0 END 程序结果:熟悉使用LDMIA,STMIA和LDR,STR指令 3.使用ARM汇编指令实现if条件执行,使用ARM汇编指令实现for条件执行,使用ARM汇编指令实现while条件执行,使用ARM汇编指令实现do…while条件执行。程序代码: 实现if条件: MOV R0,#1 MOV R1,#2 CMP R0,R1 BGT LOOP1 BLT LOOP2 LOOP1 MOV R3,R0 LOOP2 MOV R3,R1 END 程序结果: 实现for和while条件: MOV R1,#1 MOV R3,#0 MOV R2,#101;LOOP ADD R3,R1,R3 ADD R1,R1,#1 CMP R1,R2 BLT LOOP END 程序结果: 实现do…while条件: MOV R0,#1 MOV R1,#100 MOV R3,#0 LOOP CMP R0,R1 BGT STOP ADD R3,R0,R3 ADD R0,R0,#1 B LOOP STOP END 程序结果: 实验四 基于ARM的C语言程序设计 一、实验目的 1.了解ARM C语言的基本框架,学会使用ARM的C语言编程。2.掌握C语言和汇编语言编程的相互调用。 二、实验设备 1.EL-ARM-830教学实验箱,PentiumII以上的PC机,仿真器电缆。 三、ARM C语言简介与使用规则 1.ARM使用C语言编程是大势所趋 在应用系统的程序设计中,若所有的编程任务均由汇编语言来完成,其工作量巨大,并且不宜移植。由于ARM的程序执行速度较高,存储器的存储速度和存储量也很高,因此,C语言的特点充分发挥,使得应用程序的开发时间大为缩短,代码的移植十分方便,程序的重复使用率提高,程序架构清晰易懂,管理较为容易等等。因此,C语言的在ARM编程中具有重要地位。 2.ARM C语言程序的基本规则 在ARM程序的开发中,需要大量读写硬件寄存器,并且尽量缩短程序的执行时间的代码一般使用汇编语言来编写,比如ARM的启动代码,ARM的操作系统的移植代码等,除此之外,绝大多数代码可以使用C语言来完成。 C语言使用的是标准的C语言,ARM的开发环境实际上就是嵌入了一个C语言的集成开发环境,只不过这个开发环境和ARM的硬件紧密相关。 在使用C语言时,要用到和汇编语言的混合编程。当汇编代码较为简洁,则可使用直接内嵌汇编的方法,否则,使用将汇编文件以文件的形式加入项目当中,通过ATPCS的规定与C程序相互调用与访问。 ATPCS,就是ARM、Thumb的过程调用标准(ARM/Thumb Procedure Call Standard),它规定了一些子程序间调用的基本规则。如寄存器的使用规则,堆栈的使用规则,参数的传递规则等。 在C程序和ARM的汇编程序之间相互调用必须遵守ATPCS。而使用ADS的C语言编译器编译的C语言子程序满足用户指定的ATPCS的规则。但是,对于汇编语言来说,完全要依赖用户保证各个子程序遵循ATPCS的规则。具体来说,汇编语言的子程序应满足下面3个条件: ● 在子程序编写时,必须遵守相应的ATPCS规则; ● 堆栈的使用要遵守相应的ATPCS规则; ● 在汇编编译器中使用-atpcs选项。基本的ATPCS规定,请详见相关技术文档。 汇编程序调用C程序 汇编程序的设置要遵循ATPCS规则,保证程序调用时参数正确传递。在汇编程序中使用IMPORT伪指令声明将要调用的C程序函数。在调用C程序时,要正确设置入口参数,然后使用BL调用。 C程序调用汇编程序 汇编程序的设置要遵循ATPCS规则,保证程序调用时参数正确传递。 在汇编程序中使用EXPORT伪指令声明本子程序,使其他程序可以调用此子程序。在C语言中使用extern关键字声明外部函数(声明要调用的汇编子程序)。 在C语言的环境内开发应用程序,一般需要一个汇编的启动程序,从汇编的启动程序,跳到C语言下的主程序,然后,执行C程序,在C环境下读写硬件的寄存器,一般是通过宏调用,在每个项目文件的Startup44b0/INC目录下都有一个44b.h的头文件,那里面定义了所有关于44B0的硬件寄存器的宏,对宏的读写,就能操作44B0的硬件。 具体的编程规则同标准C语言。 四、实验内容 1、理解下列程序,新建工程,加入下面的程序,并观察实验结果。程序代码: /*实现5个数的相加*/ int sum5(int a,int b,int c,int d,int e){ return(a+b+c+d+e);};汇编语言 IMPORT sum5;声明调用c函数 CALLSUMS STMFD SP!,{LR};将LR寄存器入栈 MOV R0,#1;r0 = 1 ADD R1,R0,R0;r1 = 2 ADD R2,R1,R0;r2 = 3 ADD R3,R1,R2;r3 = 5 STR R3,[SP,#-4]!;将r3的值入栈当做第五个参数 ADD R3,R1,R1;R3 = R3+R1=4 BL sum5;调用sum5 ADD SP,SP,#4;sp = sp+4 LDMFD SP,{PC} 程序结果:实现了i+2i+3i+4i+5i的汇编语言调用c语言 2、用汇编语言实现1到100累加的函数,用C言语编写主程序,在主程序中调用所编写的汇编函数 程序代码: NAME asmfile PUBLIC sum5 SECTION.intvec : CODE(2)CODE32 sum5 ENTRY MOV R1,#1 MOV R2,#0 sum6 ADD R2,R1,R2 ADD R1,R1,#1 CMP R1,R0 BLE sum6 MOV PC,LR END #include 总结 本次实验主要是通过对ARM的各种指令进行操作,通过对这些指令的应用,让我们学会了如何使用汇编来进行编程,掌握汇编编程和C语言编程的技巧,并且能够熟练的使用汇编语言,深刻理解ARM的工作。并且培养了我们写代码的能力以及对代码的阅读能力和修改能力。为我们在以后的学习和生活中更实用ARM,利用汇编进行编程奠定了一定的基础!第二篇:嵌入式实验报告
第三篇:嵌入式实验报告
第四篇:嵌入式实验报告
第五篇:嵌入式实验报告