当前位置: 编程技术>移动开发
本页文章导读:
▪红别传感智能劝导系统 红外传感智能劝导系统一、项目简介:目前交通安全,文明出行是热点话题。交通方面的诸多设施都有待解决及改善,本项目以交通信号灯为研究背景,从行人的角度,节能安全为目的,来.........
▪ 树莓派IO统制 树莓派IO控制树莓派IO控制
本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明.
环境:
主机:WIN7
硬件:树莓派
说明:
参考链接:http://www.airspayce.com/mikem/bcm2835/index.html
树莓派提供.........
▪ S5PV210(TQ210)学习札记——LCD驱动编写 S5PV210(TQ210)学习笔记——LCD驱动编写网上S5PV210内核移植的文章不是很多,而描述2440和6410内核移植的文章多数是讲如何移植,而非手动编写,但是,韦东山老师的视频中讲述了如何从头编.........
[1]红别传感智能劝导系统
来源: 互联网 发布时间: 2014-02-18
红外传感智能劝导系统
一、项目简介:目前交通安全,文明出行是热点话题。交通方面的诸多设施都有待解决及改善,本项目以交通信号灯为研究背景,从行人的角度,节能安全为目的,来设计一个交通信号灯控制系统。
二、系统主要模块及作用:红外检测模块,噪声检测模块,语音提示模块,上位机控制模块。
*多对红外传感器检测人流量的大小;
**对周围环境中的声音强度进行检测;
***语音提示行人不要闯红灯;
****上位机matlab串口通信设置手动和自动检测模式,及采集噪声数据,并储存,供以后分析。
三、问题解决及目标实现:
1.能够根据人是否闯红灯,控制闯红灯提示音播报【相比较没有语音提示,或一直语音提示,有着惊醒、节能两方面的优点
2.能够根据交通信号灯周围环境大小,来控制语音播报声音大小【优点在于节能及智能化】
3.上位机能够让交通管理员手动控制语音播报,并能够实现采集信号灯周围噪声环境数据,供相关人员分析以天为周期的交通信号灯环境下人员的心理变化,环境变化。
四、总体图
图片不好上传,略。
五、工程实现
项目的所有文件已上传至我的资源
六、问题及建议
1.工程
对于硬件开发,涉及到诸多模块,每个模块必须要写成.c,.h形式方便后续调用,及裁剪
2.全局变量
全局变量一般不建议使用,但对于控制系统,模块间的信号耦合是无法避免的,而且许多全局变量的值必须要在中断里改变
volatile 关键词可以避免编译器对全局变量的使用进行优化,防止全局变量的值在中断里成功修改,而在其他模块并没有改变。
在此次项目中遇到个问题:即使加了关键词volatile ,中断里还是无法修改全局变量的值,最终经过排查,发现是由于我在两处中断里将全局变量的值分别致0,1而这两个中断服务程序的执行并不一致。
还有建议将所有的全局变量单独弄个文件,进行调用
3.时钟
对于51单片机这个单一时钟,不存在这种问题,但是对于msp430或arm等多时钟的,时钟设置尤为重要,甚至可以说如果在项目开始初没有进行很好的预制,对后续的开发及调试有着致命的影响,而且有些时钟源可以提供不同的时钟,而在不同模块中使用同一时钟源的不同时钟,相互之间是会有影响的。比如串口通信,可能会造成接收字符的不完整性。
4.程序框图
对于小的c语言文件,不画程序框图,好像不影响什么,但是对于有着诸多文件的c工程。没有程序框图,会使得后续开发缺失宏观把握,对于mcu有限的资源,不能充分利用,导致需要外接模块。各模块之间、模块与主程序之间缺乏预定的逻辑连接。
5.资源利用
在画完程序框图后,应当接着将各个模块之间所需的构件列出,比如需要定时、计数器否?采用什么方式通信。
然后在实现相应代码文件中注释好占用的管脚,内部资源,等一系列与mcu内部有关的东西
一、项目简介:目前交通安全,文明出行是热点话题。交通方面的诸多设施都有待解决及改善,本项目以交通信号灯为研究背景,从行人的角度,节能安全为目的,来设计一个交通信号灯控制系统。
二、系统主要模块及作用:红外检测模块,噪声检测模块,语音提示模块,上位机控制模块。
*多对红外传感器检测人流量的大小;
**对周围环境中的声音强度进行检测;
***语音提示行人不要闯红灯;
****上位机matlab串口通信设置手动和自动检测模式,及采集噪声数据,并储存,供以后分析。
三、问题解决及目标实现:
1.能够根据人是否闯红灯,控制闯红灯提示音播报【相比较没有语音提示,或一直语音提示,有着惊醒、节能两方面的优点
2.能够根据交通信号灯周围环境大小,来控制语音播报声音大小【优点在于节能及智能化】
3.上位机能够让交通管理员手动控制语音播报,并能够实现采集信号灯周围噪声环境数据,供相关人员分析以天为周期的交通信号灯环境下人员的心理变化,环境变化。
四、总体图
图片不好上传,略。
五、工程实现
项目的所有文件已上传至我的资源
六、问题及建议
1.工程
对于硬件开发,涉及到诸多模块,每个模块必须要写成.c,.h形式方便后续调用,及裁剪
2.全局变量
全局变量一般不建议使用,但对于控制系统,模块间的信号耦合是无法避免的,而且许多全局变量的值必须要在中断里改变
volatile 关键词可以避免编译器对全局变量的使用进行优化,防止全局变量的值在中断里成功修改,而在其他模块并没有改变。
在此次项目中遇到个问题:即使加了关键词volatile ,中断里还是无法修改全局变量的值,最终经过排查,发现是由于我在两处中断里将全局变量的值分别致0,1而这两个中断服务程序的执行并不一致。
还有建议将所有的全局变量单独弄个文件,进行调用
3.时钟
对于51单片机这个单一时钟,不存在这种问题,但是对于msp430或arm等多时钟的,时钟设置尤为重要,甚至可以说如果在项目开始初没有进行很好的预制,对后续的开发及调试有着致命的影响,而且有些时钟源可以提供不同的时钟,而在不同模块中使用同一时钟源的不同时钟,相互之间是会有影响的。比如串口通信,可能会造成接收字符的不完整性。
4.程序框图
对于小的c语言文件,不画程序框图,好像不影响什么,但是对于有着诸多文件的c工程。没有程序框图,会使得后续开发缺失宏观把握,对于mcu有限的资源,不能充分利用,导致需要外接模块。各模块之间、模块与主程序之间缺乏预定的逻辑连接。
5.资源利用
在画完程序框图后,应当接着将各个模块之间所需的构件列出,比如需要定时、计数器否?采用什么方式通信。
然后在实现相应代码文件中注释好占用的管脚,内部资源,等一系列与mcu内部有关的东西
[2] 树莓派IO统制
来源: 互联网 发布时间: 2014-02-18
树莓派IO控制
编译:
树莓派IO控制
本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明.
环境:
主机:WIN7
硬件:树莓派
说明:
参考链接:http://www.airspayce.com/mikem/bcm2835/index.html
树莓派提供若干IO,本文对其进行控制.
进行控制的IO为P1端口的11脚.
下载库文件:bcm2835-1.25.tar
链接:http://www.airspayce.com/mikem/bcm2835/bcm2835-1.25.tar.gz
安装:
tar zxvf bcm2835-1.25.tar
cd bcm2835-1.25
./configure
make
sudo make check
sudo make install
源代码:
#include <bcm2835.h>
#define PIN RPI_GPIO_P1_11
int main(int argc,char **argv)
{
if (!bcm2835_init())
{
return 1;
}
bcm2835_gpio_fsel(PIN,BCM2835_GPIO_FSEL_OUTP);
while (1)
{
bcm2835_gpio_write(PIN,HIGH);
bcm2835_delay(500);
bcm2835_gpio_write(PIN,LOW);
bcm2835_delay(500);
}
bcm2835_close();
return 0;
}编译:
gcc -o Test_Led bTest_Led.c -l bcm2835
sudo ./Test_Led
运行:
[3] S5PV210(TQ210)学习札记——LCD驱动编写
来源: 互联网 发布时间: 2014-02-18
S5PV210(TQ210)学习笔记——LCD驱动编写
网上S5PV210内核移植的文章不是很多,而描述2440和6410内核移植的文章多数是讲如何移植,而非手动编写,但是,韦东山老师的视频中讲述了如何从头编写LCD驱动,当然是以2440为例的,我看过视频之后在TQ210平台上进行了实验,实验成功,详细的原理部分以我现在的水平还难以表达清楚。下载是我自己写的代码,适用于TQ210的7寸电容屏。
测试前还需要修改下内核配置,有两个原因:
网上S5PV210内核移植的文章不是很多,而描述2440和6410内核移植的文章多数是讲如何移植,而非手动编写,但是,韦东山老师的视频中讲述了如何从头编写LCD驱动,当然是以2440为例的,我看过视频之后在TQ210平台上进行了实验,实验成功,详细的原理部分以我现在的水平还难以表达清楚。下载是我自己写的代码,适用于TQ210的7寸电容屏。
#include <linux/module.h>
#include <linux/fb.h>
#include <linux/dma-mapping.h>
#include <linux/clk.h>
static struct fb_info *lcd_info;
unsigned long pseudo_palette[16];
unsigned long *display_control;
volatile unsigned long* gpf0con;
volatile unsigned long* gpf1con;
volatile unsigned long* gpf2con;
volatile unsigned long* gpf3con;
volatile unsigned long* gpd0con;
volatile unsigned long* gpd0dat;
volatile unsigned long* vidcon0;
volatile unsigned long* vidcon1;
volatile unsigned long* vidtcon0;
volatile unsigned long* vidtcon1;
volatile unsigned long* vidtcon2;
volatile unsigned long* wincon0;
volatile unsigned long* vidosd0a;
volatile unsigned long* vidosd0b;
volatile unsigned long* vidosd0c;
volatile unsigned long* vidw00add0b0;
volatile unsigned long* vidw00add1b0;
volatile unsigned long* shodowcon;
struct clk *lcd_clk;
static inline unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf)
{
chan &= 0xffff;
chan >>= 16 - bf->length;
return chan << bf->offset;
}
static int lcdfb_setcolreg(unsigned int regno, unsigned int red,
unsigned int green, unsigned int blue,
unsigned int transp, struct fb_info *info)
{
unsigned int val;
if (regno > 16)
return 1;
/* 用red,green,blue三原色构造出val */
val = chan_to_field(red, &info->var.red);
val |= chan_to_field(green, &info->var.green);
val |= chan_to_field(blue, &info->var.blue);
//((u32 *)(info->pseudo_palette))[regno] = val;
pseudo_palette[regno] = val;
return 0;
}
static struct fb_ops lcd_fbops = {
.owner = THIS_MODULE,
.fb_setcolreg = lcdfb_setcolreg,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
};
static int lcd_init(void){
int ret;
/*分配fb_info */
lcd_info = framebuffer_alloc(0, NULL);
if(lcd_info == NULL){
printk(KERN_ERR "alloc framebuffer failed!\n");
return -ENOMEM;
}
/* 配置fb_info各成员*/
/* fix */
strcpy(lcd_info->fix.id, "s5pv210_lcd");
lcd_info->fix.smem_len = 800*480*4;
lcd_info->fix.type = FB_TYPE_PACKED_PIXELS;
lcd_info->fix.visual = FB_VISUAL_TRUECOLOR;
lcd_info->fix.line_length = 800*4;
/* var */
lcd_info->var.xres = 800;
lcd_info->var.yres = 480;
lcd_info->var.xres_virtual = 800;
lcd_info->var.yres_virtual = 480;
lcd_info->var.bits_per_pixel = 32;
lcd_info->var.red.offset = 16;
lcd_info->var.red.length = 8;
lcd_info->var.green.offset = 8;
lcd_info->var.green.length = 8;
lcd_info->var.blue.offset = 0;
lcd_info->var.blue.length = 8;
lcd_info->var.activate = FB_ACTIVATE_NOW;
lcd_info->screen_size = 800*480*4;
lcd_info->pseudo_palette = pseudo_palette;
lcd_info->fbops = &lcd_fbops;
/* 配置硬件资源*/
/* 映射内存*/
display_control = ioremap(0xe0107008,4);
gpf0con = ioremap(0xE0200120, 4);
gpf1con = ioremap(0xE0200140, 4);
gpf2con = ioremap(0xE0200160, 4);
gpf3con = ioremap(0xE0200180, 4);
gpd0con = ioremap(0xE02000A0, 4);
gpd0dat = ioremap(0xE02000A4, 4);
vidcon0 = ioremap(0xF8000000, 4);
vidcon1 = ioremap(0xF8000004, 4);
vidtcon0 = ioremap(0xF8000010, 4);
vidtcon1 = ioremap(0xF8000014, 4);
vidtcon2 = ioremap(0xF8000018, 4);
wincon0 = ioremap(0xF8000020, 4);
vidosd0a = ioremap(0xF8000040, 4);
vidosd0b = ioremap(0xF8000044, 4);
vidosd0c = ioremap(0xF8000048, 4);
vidw00add0b0 = ioremap(0xF80000A0, 4);
vidw00add1b0 = ioremap(0xF80000D0, 4);
shodowcon = ioremap(0xF8000034, 4);
/* 配置GPIO*/
*gpf0con = 0x22222222;
*gpf1con = 0x22222222;
*gpf2con = 0x22222222;
*gpf3con = 0x22222222;
*gpd0con &= ~0xf;
*gpd0con |= 0x1;
*gpd0dat |= 1<<0;
*display_control = 2<<0;
/* 使能时钟*/
lcd_clk = clk_get(NULL, "lcd");
if (!lcd_clk || IS_ERR(lcd_clk)) {
printk(KERN_INFO "failed to get lcd clock source\n");
}
clk_enable(lcd_clk);
/* 配置LCD控制器*/
*vidcon0 = (4<<6)|(1<<4);
*vidcon1 = (1<<6)|(1<<5)|(1<<4);
*vidtcon0 = (17<<16)|(26<<8)|(4<<0);
*vidtcon1 = (40<<16)|(214<<8)|(4<<0);
*vidtcon2 = (479<<11)|(799<<0);
*wincon0 &= ~(0xf<<2);
*wincon0 |= (0xb<<2);
*vidosd0a = (0<<11)|(0<<0);
*vidosd0b = (799<<11)|(479<<0);
*vidosd0c = 480*800;
//物理地址
lcd_info->screen_base = dma_alloc_writecombine(NULL,
lcd_info->fix.smem_len, (dma_addr_t *)&(lcd_info->fix.smem_start), GFP_KERNEL);
*vidw00add0b0 = lcd_info->fix.smem_start;
*vidw00add1b0 = lcd_info->fix.smem_start + lcd_info->fix.smem_len;
*shodowcon = 0x1;
//开启状态
*wincon0 |= 1;
*vidcon0 |= 3;
/* 注册fb_info */
ret = register_framebuffer(lcd_info);
return ret;
}
static void lcd_exit(void){
unregister_framebuffer(lcd_info);
dma_free_writecombine(NULL, lcd_info->fix.smem_len,
(void*)lcd_info->screen_base, (dma_addr_t)lcd_info->fix.smem_start);
iounmap(shodowcon);
iounmap(vidw00add1b0);
iounmap(vidw00add0b0);
iounmap(vidosd0c);
iounmap(vidosd0b);
iounmap(vidosd0a);
iounmap(wincon0);
iounmap(vidtcon2);
iounmap(vidtcon1);
iounmap(vidtcon0);
iounmap(vidcon1);
iounmap(vidcon0);
iounmap(gpd0dat);
iounmap(gpd0con);
iounmap(gpf3con);
iounmap(gpf2con);
iounmap(gpf1con);
iounmap(gpf0con);
framebuffer_release(lcd_info);
}
module_init(lcd_init);
module_exit(lcd_exit);
MODULE_LICENSE("GPL");
将上面的代码在自己的内核环境下编译,然后下载到开发板上试运行即可。
在安装驱动程序前执行指令:
ls /dev/fb*如果有fb0或者其他fb*存在,应该修改内和配置,取消其他fb的配置,如果看不到fb*设备,则可以按照如下步骤进行测试。
测试前还需要修改下内核配置,有两个原因:
(1) 内核默认配置下不支持Frame buffer
(2) 我们的驱动程序中用到了三个函数:
.fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit,这三个函数是引用的内核中的函数,不是我们自行实现的。
鉴于上面两个原因,我们需要配置内核支持Frame buffer和列举出的三个函数,另外,内核中并没有直接配置支持这三个函数的选项,权宜之计,修改下drivers/video目录下的Kconfig文件,在config FB项中添加
select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT添加时一定保证格式正确,参考下该文件下的其他配置项即可。配置完成后执行make menuconfig作如下配置:
Device Drivers ---> Graphics support ---> <*> Support for frame buffer devices --->配置后保存配置,编译内核并将编译好的内核下载到开发板或者NFS运行,同时将编译好的LCD驱动程序拷贝到开发板运行环境中进行安装,如果驱动文件名为lcd.ko,则执行:
insmod lcd.ko这时,你可以看到屏幕被重新初始化了。虽然LCD已经初始化了,但是不知道如何进行测试,可以按照韦东山老师视频中讲述的方法进行LCD驱动测试,但是我们移植的3.8.3内核默认不支持字库,还需要作其他配置,我是用画线的方式测试的屏幕,这里我讲一下我用的测试方法:
(1) 在Linux主机上编译下面的C++程序
#include <iostream>
unsigned long buffer[480][800] = {0};
void put_long_hex(unsigned long v){
for(int i = 0; i != 4; ++i){
std::cout.put(static_cast<char>(0xff&(v>>(8*(3-i)))));
}
}
int main(){
for(int i = 0; i != 480; ++i){
buffer[i][0] = 0x00ff0000;
buffer[i][799] = 0x0000ff00;
}
for(int i = 0; i != 800; ++i){
buffer[0][i] = 0xff000000;
buffer[479][i] = 0x00ffff00;
}
for(int i = 0; i != 480; ++i){
for(int j = 0; j != 800; ++j){
put_long_hex(buffer[i][j]);
}
}
}编译指令如下:g++ -o main main.cpp然后如下方式执行程序:
./main > /nfsroot/rootfs/test.img我是直接将文件生成在NFS的根文件系统下了,你也可以用其他方式将生成的文件拷贝到开发板运行环境内,然后执行如下指令:
cat test.img > /dev/fb0这时,就可以在屏幕上看到一个矩形且矩形的四条边颜色不相同。
如果想将驱动编译进内核,并在启动时可以看到小企鹅,可以将上面的驱动拷贝到内核的drivers/video/目录下,命名为tq210_fb.c,然后在该目录下做如下修改:
(1)修改Kconfig,添加TQ210的LCD驱动配置选项
在config FB_S4C项的后面添加如下内容:
config FB_TQ210
tristate "TQ210 lcd support"
depends on FB
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
---help---
Currently the suport is only for the TQ210(2)修改Makefile,添加如下内容:obj-$(CONFIG_FB_TQ210) += tq210_fb.o
(3)退回到内核根目录下,执行make menuconfig并按如下方式配置内核
Device Drivers ---> Graphics support ---> <*> Support for frame buffer devices ---> <*> TQ210 lcd support [*] Bootup logo ---> [*] Standard black and white Linux logo [*] Standard 16-color Linux logo [*] Standard 224-color Linux logo
如果您在开发或配置过程遇到什么问题可以留言讨论。
最新技术文章: