
495005638


0 访问量
0 原创专栏
38 资料
0 粉丝
个性签名:此E友还没有留下个性签名哦~
加入易百纳时间:2013-08-24
-
秉承从阿莫来到阿莫去的理念,受别人的帮助也要帮助别人,使用TIM4的CHANNEL2进行脉冲捕获使用的超声波模块程序,欢迎使用 附件:超声波.zip2013-08-300 0 2938
-
由于还没仔细整理,这也是在前人的基础上移植而来的,所以会比较乱,不过在STM32F4 Discover 驱动TFT液晶还是可以的。 说明一下本驱动针对的是SSD1289控制器的TFT,对于其他的液晶,大家自行修改初始化部分吧,也就是修改写寄存器和寄存器的值。在另一个贴中我说明了关于白色显示的问题,大家可以看看。由于是使用排线连接的所以,驱动白色的时候就是出问题,这个原因可能是排线连接的问题,如果可以大家自己画个PCB转接板,应该就能解决了。我也在画图测试中。 附件:TFT.zip2013-08-273 0 3334
-
自己根据官方库函数写的一个历程,上传 附件:6050.rar2013-08-270 0 2553
-
本帖最后由 495005638 于 2013-8-27 16:33 编辑 画PCB的时候用到的一个小工具,蛮不错的。 不知道各位大侠还有什么好工具,一起分享一下。 附件:BMP.rar2013-08-270 0 2473
-
红外遥控器原理 我这里就不多说了,如果需要了解的 请网上寻找相关资料 基于市面上的家电遥控器绝大多数是38khz的载波,所以我们这次也选择只学习和控制38khz的。 学习型的原理:采样学习遥控器波形——存储波形数据——发送相应的波形 三步骤就完成了自学习红外转发的功能。 当然最好有淘宝网上的那种百来块的逻辑分析仪会让你的工作事半功倍。 1、采样学习遥控器波形 接收头为了图方便 使用一体化红外接收头 主要是38k载波的 tim2 90us 采样用。 学习键值:主要实现的原理是基于一般的红外高低电平大概是560US 所以我们用90us去采集, 我用的最简单的方法,定时去判断io口状态,然后保存起来。 当然也可以用pwm高低电平的输入捕获,保存每次跳变的时间,我觉得有点麻烦 以前没用过,所以就用个最简单的方法。 程序如下: bTIM2Flag是90us定时器2,每次定时时间到之后 bTIM2Flag = TRUE; void Receve_Data(u8 * data,u16 len) { u8 buf=0; u16 i,j; for(i=0;i { buf=0; for(j=0;j<8;) { if(bTIM2Flag) { buf=buf<<1; if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_4)==0) { buf|=1; } j++; bTIM2Flag = FALSE; } data = buf; } } } 2、存储波形数据 通过上面的工作,每个键的学习你可以得到200~500个数据 ,为什么差别在吗大呢? 原因是这样:电视机遥控器 机顶盒 dvd等这些常用的都是单键值遥控器,比如开机关机是同一个键值。 但是空调就是不一样了,虽然是按下同一个按键,开机和关机键不一样。 不同的温度,不同的模式,输出的都是不是一样的,也就是说 如果你想学空调的键值,空调的每个状态你都必须要学习。 当然我觉得没必要空调的学习完所有状态,学习常用的温度常用的模式之间组合就差不多了。 这时候你需要用另外的定时器tim3做一个38khz的载波,条件成立时候bSendFlag = TRUE 让红外发射控制管脚不停的取反。条件不成立bSendFlag = FALSE,tim3 不控制发射引脚 ,很简单吧。 然而你应该什么时候 设置bSendFlag 的值呢? 应该是进入发送程序时候,你就判断发送数据里面,判断要发送的每个数据,比如0xff 或者0x3f,你就知道0xff 是8位都是 bSendFlag = TRUE。 0x3f 你应该知道前后6位时候是bSendFlag = TRUE ,高2位是bSendFlag = FALSE。 程序如下: void Send_Data(u8 * data,u16 len) { u8 buf; u16 i,j; for(i=0;i { buf = data; for(j=0;j<8;) { if(bTIM2Flag) { if(buf &0x80) { bSendFlag = TRUE; } else { bSendFlag = FALSE; } j++; buf=buf<<1; bTIM2Flag = FALSE; } } } bTIM2Flag = FALSE; while(!bTIM2Flag); bSendFlag = FALSE; } 通过这样就可以完成学习和发送的功能了。 很简单但是比较实用。 附件:112421jjpjttt6umj20t2z.pdf2013-08-270 0 3413
-
开发环境: Keil 3.9 正点原子的平台 固件库 3.5 自已写的驱动放在Drive下 ========================================== 以下是硬件连接 *** Nokia5110 ************************************* Nokia5110_RST --------C0 Nokia5110_SCE --------C1 Nokia5110_DC --------C2 Nokia5110_DN --------C3 Nokia5110_SCLK--------C4 Nokia5110_LED --------C5 *** DS1302 ************************************************ DS1302_RST ----------B13 DS1302_IO ----------B14 DS1302_SCLK ----------B15 *** I2C **************************************************** I2C_SDA -------------B5 I2C_SCL -------------B6 *** DS18B20 ************************************************ DS18B20_PIN ----------B8 附件:5110.rar 附件:DS18B20.rar 附件:DS1302.rar2013-08-260 0 2706
-
本帖最后由 495005638 于 2013-8-26 12:00 编辑 废话后面说,先直接上OV7670寄存器的配置部分 const uint8_t OV7670_Reg[][2]= { //Frame Rate Adjustment for 24Mhz input clock //30fps PCLK=24MHz {0x11, 0x80},//软件应用手册上设置的是0x80,例程设置的是0x00 {0x6b, 0x0a},//PLL控制,软件应用手册上设置的是0x0a,例程设置的是0x40,将PLL调高的话就会产生花屏 {0x2a, 0x00}, {0x2b, 0x00}, {0x92, 0x00}, {0x93, 0x00}, {0x3b, 0x0a}, //Output format {0x12, 0x14},//QVGA(320*240)、RGB //RGB555/565 option(must set COM7[2] = 1 and COM7[0] = 0) {0x40, 0x10},//RGB565,effective only when RGB444[1] is low {0x8c, 0x00}, //Special effects - 特效 //normal {0x3a, 0x04}, {0x67, 0xc0}, {0x68, 0x80}, //Mirror/VFlip Enable - 水平镜像/竖直翻转使能 {0x1e, 0x37},//修改配置值将产生图像显示上下或左右颠倒 //Banding Filter Setting for 24Mhz Input Clock - 条纹滤波器 //30fps for 60Hz light frequency //{0x13, 0xe7},//banding filer enable //{0x9d, 0x98},//50Hz banding filer //{0x9e, 0x7f},//60Hz banding filer //{0xa5, 0x02},//3 step for 50Hz //{0xab, 0x03},//4 step for 60Hz //{0x3b, 0x02},//select 60Hz banding filer //Simple White Balance - 白平衡 //{0x13, 0xe7},//AWB、AGC、AGC Enable and ... //{0x6f, 0x9f},//simple AWB //AWBC - 自动白平衡控制(Automatic white balance control) //{0x43, 0x14},//用户手册里这些寄存器的值都是保留(Reserved),不用设置的呀? //{0x44, 0xf0}, //{0x45, 0x34}, //{0x46, 0x58}, //{0x47, 0x28}, //{0x48, 0x3a}, //AWB Control //{0x59, 0x88},//用户手册连寄存器都是保留,初始值都没提供 //{0x5a, 0x88}, //{0x5b, 0x44}, //{0x5c, 0x67}, //{0x5d, 0x49}, //{0x5e, 0x0e}, //AWB Control //{0x6c, 0x0a}, //{0x6d, 0x55}, //{0x6e, 0x11}, //{0x6f, 0x9f}, //AGC/AEC - Automatic Gain Control自动增益补偿/Automatic exposure Control自动曝光控制 //{0x00, 0x00}, //{0x14, 0x20}, //{0x24, 0x75}, //{0x25, 0x63}, //{0x26, 0xA5}, //AEC algorithm selection - AEC公式选择 //{0xaa, 0x94},//基于平均值的AEC算法Average-based AEC algorithm/基于直方图的AEC算法Histogram-based AEC algorithm //基于直方图的AGC/AEC的控制 //{0x9f, 0x78}, //{0xa0, 0x68}, //{0xa6, 0xdf}, //{0xa7, 0xdf}, //{0xa8, 0xf0}, //{0xa9, 0x90}, //Fix Gain Control - 固定增益控制 //{0x69, 0x5d},//Fix gain for Gr channel/for Gb channel/for R channel/for B channel //Color saturation 颜色饱和度 + 0 //{0x4f, 0x80}, //{0x50, 0x80}, //{0x51, 0x00}, //{0x52, 0x22}, //{0x53, 0x5e}, //{0x54, 0x80}, //{0x58, 0x9e}, //Brightness - 亮度 + 0 //{0x55, 0x00}, //Contrast - 对比度 + 0 //{0x56, 0x40}, //Gamma Curve - 伽马曲线 //{0x7a, 0x20}, //{0x7b, 0x1c}, //{0x7c, 0x28}, //{0x7d, 0x3c}, //{0x7e, 0x55}, //{0x7f, 0x68}, //{0x80, 0x76}, //{0x81, 0x80}, //{0x82, 0x88}, //{0x83, 0x8f}, //{0x84, 0x96}, //{0x85, 0xa3}, //{0x86, 0xaf}, //{0x87, 0xc4}, //{0x88, 0xd7}, //{0x89, 0xe8}, //Matrix Coefficient - 色彩矩阵系数 //{0x4f, 0x80}, //{0x50, 0x80}, //{0x51, 0x00}, //{0x52, 0x22}, //{0x53, 0x5e}, //{0x54, 0x80}, //Lens Correction Option - 镜头补偿选项 //{0x62, 0x00}, //{0x63, 0x00}, //{0x64, 0x04}, //{0x65, 0x20}, //{0x66, 0x05}, //{0x94, 0x04},//effective only when LCC5[2] is high //{0x95, 0x08},//effective only when LCC5[2] is high //注释这些配置的话,就倾斜显示,并显示多块,这到底是控制什么的?跟时序图有关? {0x17, 0x16},//行频Horizontal Frame开始高八位(低三位在HREF[2:0]) {0x18, 0x04},//行频Horizontal Frame结束高八位(低三位在HREF[5:3]) {0x19, 0x02},//场频Vertical Frame开始高八位(低二位在VREF[1:0]) {0x1a, 0x7b},//场频Vertical Frame结束高八位(低二位在VREF[3:2]) {0x32, 0x80},//HREF {0x03, 0x06},//VREF //注释这个配置的话,就显示花屏了 {0x15, 0x02},//配置PCLK、HREF、VSYNC相关 //Automatic black Level Compensation - 自动黑电平校正 {0xb0, 0x84},//调试时注释这项配置时,颜色显示不正常了,红色练绿色,绿色变红色,但用户手册对这寄存器是保留RSVD //{0xb1, 0x0c}, //{0xb2, 0x0e}, //{0xb3, 0x82}, //{0xb8, 0x0a}, //SCALING_xx寄存器 //{0x70, 0x00}, //{0x71, 0x00}, //{0x72, 0x11}, //{0x73, 0x08}, //{0x3e, 0x00}, //ADC //{0x37, 0x1d},//ADC控制ADC Control //{0x38, 0x71},//ADC和模拟共模控制ADC and Analog Common Mode Control //{0x39, 0x2a},//ADC偏移控制ADC Offset Control //零杂的寄存器 //{0x92, 0x00},//空行低八位Dummy Line low 8 bits //{0xa2, 0x02},//像素时钟延时 //{0x0c, 0x0c}, //{0x10, 0x00}, //{0x0d, 0x01}, //{0x0f, 0x4b}, //{0x3c, 0x78}, //{0x74, 0x19}, //用户手册里这几个寄存器都是保留RSVD //{0x0e, 0x61}, //{0x16, 0x02}, //{0x21, 0x02}, //{0x22, 0x91}, //{0x29, 0x07}, //{0x33, 0x0b}, //{0x35, 0x0b}, //{0x4d, 0x40}, //{0x4e, 0x20}, //{0x8d, 0x4f}, //{0x8e, 0x00}, //{0x8f, 0x00}, //{0x90, 0x00}, //{0x91, 0x00}, //{0x96, 0x00}, //{0x9a, 0x80}, }; 刚开始学OV7670摄像头,我想大家跟我一样心里很毛躁吧,一个模块需要你配置100多个寄存器,但用户手册对寄存器的介绍却草草的一笔带过,自己无从下手啊,只能看开发板给的例程和上网找一些大虾的帖子了。虽然开发板提供的例程好用,但是光用别人的配置不行,怎么也得根据自己实际的需要去修改这些寄存器的配置,所以就静下心里好好看中英文用户手册和OV7670_software_application_note文档。中文用户手册翻译错误太多,建议看英文的,还有强烈推荐看下OV7670_software_application_note文档,文中简单介绍了针对不同的模式对OV7670寄存器设置。 遇到问题我喜欢化繁为简,挑重点的先解决。看到OV7670寄存器中挺多设置是针对摄像头拍摄图像质量方面的,比如自动白平衡(AWB)、自动曝光控制(AEC)等等,当不知道摄像头拍摄的图片是否能在LCD上正常显示时,你修改这部分配置只能说是做无用功。所以首要任务是让摄像头拍摄的图像能显示在LCD上,我用“//”注释了暂时对于我们来说无关紧要的寄存器配置,100多个寄存器,现在只需要配置20多个,一目了然了吧,如果你的摄像头采集的图像不能在LCD上正常显示,参照用户手册修改这20多项即可,当然得先保证相关的硬件接口正确。后期为了调节图像效果,去掉相应的“//”注释符即可。 这是自己通过调试归纳总结的,希望能对大家有点帮助吧,大家一起交流,共同进步。 附件:附件:OV7670 中文版数据手册.pdf2013-08-262 0 4742
-
实现的功能: 1、日历功能。 2、数字和模拟时钟功能。 要点分析: 1、STM32自带了RTC时钟计数器,从0开始计数到232。每一个计数代表秒计数,每六十个计数代表分计数,以此类推。24(小时)*60(分钟)*60(秒钟)=86400代表一天的计数时间。假设当前计数为count,count/86400得到计数的天数,根据这个得到年月日。Count%86400得到时分秒。 2、一些根据1中得到的年月日时分秒,进行计算的程序有:阳历转阴历,闰年判断,节气判断,星期几计算,当前月有多少天等等。 3、模拟时钟的绘制:时钟指针运动算法、屏幕重绘方法、RTC消息、画笔/画刷等。指针运动算法和屏幕重绘方法是本程序主要难点所在。(以下参照百度文库之模拟时钟) 不论何种指针,每次转动均以π/30弧度(一秒的角度)为基本单位,且都以表盘中心为转动圆心。计算指针端点(x, y)的公式如下: x =圆心x坐标 + 指针长度 * cos (指针方向角) y =圆心y坐标 + 指针长度 * sin (指针方向角) 注意,指针长度是指自圆心至指针一个端点的长度(是整个指针的一部分),由于指针可能跨越圆心,因此一个指针需要计算两个端点。 由于屏幕的重绘1秒钟一次,如果采用全屏删除式重绘则闪烁十分明显,显示效果不佳。本程序采用非删除式重绘,假定指针将要移动一格,则先采用背景色(这里是白色)重绘原来指针以删除原来位置的指针,再采用指针的颜色在当前位置绘制指针(如果指针没有动,则直接绘制指针,此句在程序中被我删除,具体原因,为数据截断导致一些误差)。 另外,秒表为RTC一秒钟定时计数。 程序分析: uCGUI+uCOS,一共三个任务:主处理任务、触摸屏任务、秒更新任务。 void App_UCGUI_TaskCreate (void) { CPU_INT08U os_err; os_err = os_err; Clock_SEM=OSSemCreate(1); //建立秒更新中断的信号量 //硬件平台初始化 BSP_Init(); //主处理任务--------------------------------------------------------- os_err = OSTaskCreateExt(AppTaskUserIF, (void *)0, (OS_STK *)&AppTaskUserIFStk[APP_TASK_USER_IF_STK_SIZE-1], APP_TASK_USER_IF_PRIO, APP_TASK_USER_IF_PRIO, (OS_STK *)&AppTaskUserIFStk[0], APP_TASK_USER_IF_STK_SIZE, (void *)0, OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR); //触摸屏任务--------------------------------------------------------- os_err = OSTaskCreateExt(AppTaskKbd, (void *)0, (OS_STK *)&AppTaskKbdStk[APP_TASK_KBD_STK_SIZE-1], APP_TASK_KBD_PRIO, APP_TASK_KBD_PRIO, (OS_STK *)&AppTaskKbdStk[0], APP_TASK_KBD_STK_SIZE, (void *)0, OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR); //秒更新任务 os_err = OSTaskCreateExt(Clock_Updata, (void *)0, (OS_STK *)&Clock_Updata_Stk[Clock_Updata_STK_SIZE-1], Clock_Updata_PRIO, Clock_Updata_PRIO, (OS_STK *)&Clock_Updata_Stk[0], Clock_Updata_STK_SIZE, (void *)0, OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR); } 万年历中的时间用的是STM32自带的RTC实时时钟。 1、主处理任务:界面背景初始化,并根据当前时间,画出图1的数据。 static void AppTaskUserIF (void *p_arg) { (void)p_arg; INT8U err; //界面初始化 GUI_Init(); //ucgui 初始化 _ExecCalibration(); /* 触摸屏校准 */ GUI_SetBkColor(GUI_WHITE); //设置背景色 GUI_SetColor(GUI_GRAY); //设置前景色 GUI_Clear(); //清屏 Lcd_show_bmp(0, 0,"/RTC.bmp"); //显示万年历背景 GUI_SetFont(&GUI_FontHZ_SimSun_16); GUI_DispStringAt("一",15,47); //显示星期一 GUI_DispStringAt("二",44,47); //显示星期二 GUI_DispStringAt("三",73,47); //显示星期三 GUI_DispStringAt("四",102,47); //显示星期四 GUI_DispStringAt("五",131,47); //显示星期五 GUI_SetColor(GUI_RED); //用红字显示周末 GUI_DispStringAt("六",160,47); //显示星期六 GUI_DispStringAt("日",189,47); //显示星期日 to_tm(RTC_GetCounter(), &s_time); //根据RTC时钟得到万年历时间的初值,注意,这个值是根据用户查询万年历变化 GUI_SetFont(&GUI_Font16_1 ); //设置英文字体 GUI_DispDecAt(s_time.tm_year,4,13,4);//显示万年历的年份 GUI_SetFont(&GUI_FontHZ_SimSun_16); //设置中文字体 GUI_DispString("年"); //显示年 GUI_SetFont(&GUI_Font16_1 ); //设置英文字体 GUI_DispDec(s_time.tm_mon,2); //显示万年历的月份 GUI_SetFont(&GUI_FontHZ_SimSun_16); //设置中文字体 GUI_DispString("月"); //显示月 GUI_SetFont(&GUI_Font16_1 ); //设置英文字体 GUI_DispDec(s_time.tm_mday,2); //显示万年历的日子 GUI_SetFont(&GUI_FontHZ_SimSun_16);//设置中文字体 GUI_DispString("日"); //显示日 //画模拟时钟界面 u16 index,x,y; GUI_SetPenSize(1); GUI_SetColor(GUI_RED); GUI_DrawCircle(264,170, 45); //画时钟最外层的圆, for( index = 0; index < 60; index++ )//画时钟的刻度 { x = -(40* cos(( index * 6 ) * DEG2RAD)) + 264; y = -(40* sin(( index * 6 ) * DEG2RAD)) + 170; if( index % 5 == 0 ) { GUI_SetPenSize(4); //指示为小时的刻度用粗点画 } else { GUI_SetPenSize(2); //其它刻度用西点画 } GUI_DrawPoint( x, y ); } while(1) { RTC_Show(RTC_GetCounter()); //主任务执行程序,接下来分析 OSTimeDlyHMSM(0,0,0,10); } } //主任务执行程序 void RTC_Show(uint32_t TimeVar) { u8 str[15]; // 字符串暂存 u8 i,k; static flag=0; #if (GUI_SUPPORT_CURSOR|GUI_SUPPORT_TOUCH) GUI_CURSOR_Show(); //鼠标显示 #endif WM_SetCreateFlags(WM_CF_MEMDEV); /* Automatically use memory devices on all windows */ if(flag==0) //初始化按键,只执行一次。 { //建立按键F1-F5 _ahButton[0] =BUTTON_Create(5, 0, 32,13, GUI_KEY_F1 , WM_CF_SHOW | WM_CF_STAYONTOP | WM_CF_MEMDEV); _ahButton[1]=BUTTON_Create(5, 29, 32,13, GUI_KEY_F2 , WM_CF_SHOW | WM_CF_STAYONTOP | WM_CF_MEMDEV); _ahButton[2]=BUTTON_Create(53, 0, 16,13, GUI_KEY_F3 , WM_CF_SHOW | WM_CF_STAYONTOP | WM_CF_MEMDEV); _ahButton[3]=BUTTON_Create(53,29,16,13, GUI_KEY_F4 , WM_CF_SHOW | WM_CF_STAYONTOP | WM_CF_MEMDEV); _ahButton[4]=BUTTON_Create(85, 0, 16,13, GUI_KEY_F5, WM_CF_SHOW | WM_CF_STAYONTOP | WM_CF_MEMDEV); _ahButton[5]=BUTTON_Create(85,29, 16,13, GUI_KEY_F6, WM_CF_SHOW | WM_CF_STAYONTOP | WM_CF_MEMDEV); //按键字体设置 BUTTON_SetFont(_ahButton[0],&GUI_Font6x8);//GUI_Font16_ASCII BUTTON_SetFont(_ahButton[1],&GUI_Font6x8);//GUI_Font16_ASCII BUTTON_SetFont(_ahButton[2],&GUI_Font6x8);//GUI_Font16_ASCII BUTTON_SetFont(_ahButton[3],&GUI_Font6x8);//GUI_Font16_ASCII BUTTON_SetFont(_ahButton[4],&GUI_Font6x8);//GUI_Font16_ASCII BUTTON_SetFont(_ahButton[5],&GUI_Font6x8);//GUI_Font16_ASCII //按键背景色设置 BUTTON_SetBkColor(_ahButton[0],0,GUI_DARKMAGENTA); //按键背景颜色 BUTTON_SetBkColor(_ahButton[1],0,GUI_DARKMAGENTA); BUTTON_SetBkColor(_ahButton[2],0,GUI_DARKMAGENTA); BUTTON_SetBkColor(_ahButton[3],0,GUI_DARKMAGENTA); BUTTON_SetBkColor(_ahButton[4],0,GUI_DARKMAGENTA); BUTTON_SetBkColor(_ahButton[5],0,GUI_DARKMAGENTA); //按键前景色设置 BUTTON_SetTextColor(_ahButton[0],0,GUI_WHITE); BUTTON_SetTextColor(_ahButton[1],0,GUI_WHITE); BUTTON_SetTextColor(_ahButton[2],0,GUI_WHITE); BUTTON_SetTextColor(_ahButton[3],0,GUI_WHITE); BUTTON_SetTextColor(_ahButton[4],0,GUI_WHITE); BUTTON_SetTextColor(_ahButton[5],0,GUI_WHITE); //按键显示字符 BUTTON_SetText(_ahButton[0], "+"); BUTTON_SetText(_ahButton[1], "-"); BUTTON_SetText(_ahButton[2], "+"); BUTTON_SetText(_ahButton[3], "-"); BUTTON_SetText(_ahButton[4], "+"); BUTTON_SetText(_ahButton[5], "-"); flag=1; } u8 key = GUI_GetKey(); //实时获得触摸按键的值 if(key==40) //年数增加按钮 { s_time.tm_year++; //F1 if(s_time.tm_year>2099) //超过范围处理 s_time.tm_year=1970; } else if(key==41) //年数减小按钮 { s_time.tm_year--; //F2 if(s_time.tm_year<1900) //超过范围处理 s_time.tm_year=2099; } else if(key==42) //月数增加按钮 { s_time.tm_mon++; //F3 if(s_time.tm_mon>12) //超过范围处理 { s_time.tm_mon=1; } } else if(key==43) //月数减小按钮 { s_time.tm_mon--; //F4 if(s_time.tm_mon<0) //超过范围处理 { s_time.tm_mon=12; } } else if(key==44) //日数增加按钮 { s_time.tm_mday++; //F5 if(s_time.tm_mday>getDays(s_time.tm_year,s_time.tm_mon)) //超过范围处理 { s_time.tm_mday=1; } } else if(key==45) //日数减小按钮 { s_time.tm_mday--; //F6 if(s_time.tm_mday<0) //超过范围处理 { s_time.tm_mday=getDays(s_time.tm_year,s_time.tm_mon); } } GUI_SetFont(&GUI_Font16_1 ); GUI_DispDecAt(s_time.tm_year,4,13,4); //显示万年历的年数 GUI_SetFont(&GUI_FontHZ_SimSun_16); GUI_DispString("年"); //显示年 GUI_SetFont(&GUI_Font16_1 ); GUI_DispDec(s_time.tm_mon,2); //显示万年历的月数 GUI_SetFont(&GUI_FontHZ_SimSun_16); GUI_DispString("月"); //显示月 GUI_SetFont(&GUI_Font16_1 ); GUI_DispDec(s_time.tm_mday,2); //显示万年历的日数 GUI_SetFont(&GUI_FontHZ_SimSun_16); GUI_DispString("日"); //显示日 GUI_DispString(" "); GetChinaCalendarStr((u16)systmtime.tm_year,(u8)systmtime.tm_mon,(u8)systmtime.tm_mday,str); //阳历转阴历 //见下面子程序1 GUI_DispString(str); //显示阴历 GUI_SetColor(GUI_RED); //字体颜色 GUI_DispString("竹天笑万年历"); k=getWeekDay(s_time.tm_year,s_time.tm_mon,1); //得到某年某月的第一天的星期数 //见下面子程序2 GUI_GotoXY(18,69); .//位置设定 GUI_SetFont(&GUI_Font6x8); //万年历日子显示 for(i=1;i<=40;i++) //第一行最少显示一个,第六行最多显示二个,i的上限只需要大于37即可 { if(igetDays(s_time.tm_year,s_time.tm_mon)+k) //本月1号前和最后一天后的格子显示清零 { //见子程序3 GUI_DispString(" "); //显示空格,用于清除之前数据 } else { if((i+1)%7==0||i%7==0) //如果为星期六和星期天,字体设置为红色 { GUI_SetColor(GUI_RED); } else //否则为黑色 { GUI_SetColor(GUI_BLACK); } if(i==s_time.tm_mday+k) //如果该天为所选日期,设置背景为黄色 { GUI_SetBkColor(GUI_YELLOW); } GUI_DispDecSpace(i-k,2); //显示日子 GUI_SetBkColor(GUI_WHITE); //恢复之前背景色 } GUI_GotoXY(GUI_GetDispPosX()+17,GUI_GetDispPosY()); //光标移动到下一个格子 if(i%7==0) { GUI_GotoXY(18,GUI_GetDispPosY()+27); //7天换行显示 } } GUI_GotoXY(12,79); //光标移动到下一行首行 GUI_SetFont(&GUI_FontHZ_SimSun_11); //显示为初几,若为节气则显示节气 for(i=1;i<=40;i++) { if(igetDays(s_time.tm_year,s_time.tm_mon)+k) //本月1号前和最后一天后的格子显示清零 { GUI_DispString(" "); //显示两个中文空格,占两个中文字符 } else { if(GetJieQiDay((u16)s_time.tm_year, (u8)s_time.tm_mon, i-k, str)==1) //如果为节气 { //见子程序4 GUI_SetColor(GUI_MAGENTA); //设置字体为橙色 } else { GUI_SetColor(GUI_BLUE); //正常显示蓝色 } if(i==s_time.tm_mday+k) //如果该天为所选日期,设置背景为黄色 { GUI_SetBkColor(GUI_YELLOW); } GUI_DispString(str); //显示阴历号 GUI_SetBkColor(GUI_WHITE); //恢复背景色 } GUI_GotoXY(GUI_GetDispPosX()+7,GUI_GetDispPosY()); if(i%7==0) { GUI_GotoXY(12,GUI_GetDispPosY()+27); } } WM_ExecIdle(); //刷新屏幕 #defineDEG2RAD (3.1415926f / 180) GUI_POINT m_Hour[2],m_Sec[2],m_Min[2]; //时分秒两个端点 static GUI_POINT m_OldHour[2],m_OldMin[2],m_OldSec[2]; //时分秒之前的两个端点 m_Hour[0].x=-20*cos((systmtime.tm_hour*30+90)*DEG2RAD)+264; //时钟指针端点计算,每一时旋转30 m_Hour[0].y=-20*sin((systmtime.tm_hour*30+90)*DEG2RAD)+170; //度,逆时针旋转,当前时钟*30得旋 m_Hour[1].x=-2*cos((systmtime.tm_hour*30+270)*DEG2RAD)+264; //转的度数, 时钟另一端加上180度 m_Hour[1].y=-2*sin((systmtime.tm_hour*30+270)*DEG2RAD)+170; //将极坐标形式转换成直角坐标 GUI_SetColor(GUI_WHITE); //重绘上一次时钟指针覆盖的背景 GUI_DrawLine(m_OldHour[0].x,m_OldHour[0].y, m_OldHour[1].x,m_OldHour[1].y); GUI_SetColor(GUI_RED); //画新的时钟指针 GUI_DrawLine(m_Hour[0].x,m_Hour[0].y, m_Hour[1].x,m_Hour[1].y); m_Min[0].x=-30*cos((systmtime.tm_min*6+90)*DEG2RAD)+264; //分钟指针端点计算,每一分旋转6 m_Min[0].y=-30*sin((systmtime.tm_min*6+90)*DEG2RAD)+170; //度,逆时针旋转,当前分钟*6得旋 m_Min[1].x=-4*cos((systmtime.tm_min*6+270)*DEG2RAD)+264; //转的度数, 时钟另一端加上180度 m_Min[1].y=-4*sin((systmtime.tm_min*6+270)*DEG2RAD)+170; //将极坐标形式转换成直角坐标 GUI_SetColor(GUI_WHITE); //重绘上一次分钟指针覆盖的背景 GUI_DrawLine(m_OldMin[0].x,m_OldMin[0].y, m_OldMin[1].x,m_OldMin[1].y); GUI_SetColor(GUI_BLUE); //画新的分钟指针 GUI_DrawLine(m_Min[0].x,m_Min[0].y, m_Min[1].x,m_Min[1].y); m_Sec[0].x=-35*cos((systmtime.tm_sec*6+90)*DEG2RAD)+264; //分钟指针端点计算,每一秒旋转6 m_Sec[0].y=-35*sin((systmtime.tm_sec*6+90)*DEG2RAD)+170; //度,逆时针旋转,当前秒钟*6得旋 m_Sec[1].x=-8*cos((systmtime.tm_sec*6+270)*DEG2RAD)+264; //转的度数, 时钟另一端加上180度 m_Sec[1].y=-8*sin((systmtime.tm_sec*6+270)*DEG2RAD)+170; //将极坐标形式转换成直角坐标 GUI_SetColor(GUI_WHITE); GUI_DrawLine(m_OldSec[0].x,m_OldSec[0].y, m_OldSec[1].x,m_OldSec[1].y); GUI_SetColor(GUI_BLACK); GUI_DrawLine(m_Sec[0].x,m_Sec[0].y, m_Sec[1].x,m_Sec[1].y); for(i=0;i<2;i++) { m_OldHour=m_Hour; //保存当前时分秒指针 m_OldMin=m_Min; m_OldSec=m_Sec; } /* 输出公历时间 */ GUI_SetFont(&GUI_Font16_1 ); GUI_DispDecAt(systmtime.tm_year, 240, 60,4); //显示当前年 GUI_DispString("-"); GUI_DispDec(systmtime.tm_mon,2); //显示当前月 GUI_DispString("-"); GUI_DispDec(systmtime.tm_mday,2); //显示当前日 GUI_DispDecAt(systmtime.tm_hour,240,76,2); //显示当前时 GUI_DispString(":"); GUI_DispDec(systmtime.tm_min,2); //显示当前分 GUI_DispString(":"); GUI_DispDec(systmtime.tm_sec,2); //显示当前秒 GUI_SetFont(&GUI_FontHZ_SimSun_16); GUI_DispStringAt("星期",240,92); //显示当前星期 GUI_DispString(WEEK_STR[systmtime.tm_wday]); } 子程序1 ////////////////////////////////////////////////////////////////////////////////////////////////////////// // 函数名称:GetChinaCalendarStr // 功能描述:输入公历日期得到农历字符串 // 如:GetChinaCalendarStr(2007,02,06,str) 返回str="丙戌年腊月十九" // 输 入: year 公历年 // month 公历月 // day 公历日 // str 储存农历日期字符串地址 15Byte // 输 出: 无 ///////////////////////////////////////////////////////////////////////////////////////////////////////// void GetChinaCalendarStr(u16 year,u8 month,u8 day,u8 *str) { u8 NLyear[4]; u8 SEyear; StrCopy(&str[0],(u8 *)"甲子年正月初一",15); if(GetChinaCalendar(year,month,day,(u8 *)NLyear)==0) return; //GetChinaCalendar见子程序5,转化为阴历 GetSkyEarth(NLyear[0]*100+NLyear[1],&SEyear); StrCopy(&str[0],(u8 *) sky[SEyear%10],2); // 甲 StrCopy(&str[2],(u8 *)earth[SEyear%12],2); // 子 if(NLyear[2]==1) StrCopy(&str[6],(u8 *)"正",2); else StrCopy(&str[6],(u8 *)monthcode[NLyear[2]-1],2); if(NLyear[3]>10) StrCopy(&str[10],(u8 *)nongliday[NLyear[3]/10],2); else StrCopy(&str[10],(u8 *)"初",2); StrCopy(&str[12],(u8 *)monthcode[(NLyear[3]-1)%10],2); } 子程序2 u8 getWeekDay(u16 y, u8 m, u8 d) //得到指定年月日的星期数 { if (m == 1) m = 13; if (m == 2) m = 14; u8 week = (d + 2 * m + 3 * (m + 1) / 5 + y + y / 4 - y / 100 + y / 400) % 7 + 1; return week; } 子程序3 /* *判断是否闰年 *参数: y 整型, 接收年份值 *返回值: 整型, 只为0或1, 0代表假, 1代表真 */ u8 isRunNian(u16 y) { return (y % 4 == 0 && y % 100 != 0 || y % 400 == 0) ? 1 : 0; } /* *计算某个月的天数 *参数: y 整型,接收年份值; m 整型,接收月份值; *返回值: 整型, 是0, 28, 29, 30, 31之间的一个数 *注意: 返回值为0,表示你调用该函数时传递了不正确的年份值或月份值. */ u8 getDays(u16 y, u8 m) { u8 days = 0; switch(m) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: days = 31; break; case 4: case 6: case 9: case 11: days = 30; break; case 2: days = isRunNian(y) ? 29 : 28; break; default:; } return days; } 子程序4 ////////////////////////////////////////////////////////////////////////////////////////////////////////// // 函数名称:GetJieQiDay // 功能描述:输入公历日期得到24节气字符串 // 是否为节气 // 输 入: year 公历年 // month 公历月 // day 公历日 // str 储存24节气字符串地址 5Byte // 输 出: 1 成功 // 0 失败 ///////////////////////////////////////////////////////////////////////////////////////////////////////// u8 GetJieQiDay(u16 year,u8 month,u8 day,u8 *str) { u8 JQdate,JQ; u8 NLyear[4]; StrCopy(&str[0],(u8 *)"初一",5); if(GetJieQi(year,month,day,&JQdate)==0) return 0; JQ = (month-1) *2 ; //获得节气顺序标号(0~23 if(day >= 15) JQ++; //判断是否是上半月 if(day==JQdate) //今天正是一个节气日 { StrCopy(str,(u8 *)JieQiStr[JQ],5); return 1; } //今天不是一个节气日 else { GetChinaCalendar(year,month,day,(u8 *)NLyear); if(NLyear[3]>10) StrCopy(&str[0],(u8 *)nongliday[NLyear[3]/10],2); else StrCopy(&str[0],(u8 *)"初",2); StrCopy(&str[2],(u8 *)monthcode[(NLyear[3]-1)%10],2); return 0; } } 子程序5 ///////////////////////////////////////////////////////////////////////////////////////////////////////// // 函数名称:GetChinaCalendar //功能描述:公农历转换(只允许1901-2099年) // 输 入: year 公历年 // month 公历月 // day 公历日 // p 储存农历日期地址 // 输 出: 1 成功 // 0 失败 ///////////////////////////////////////////////////////////////////////////////////////////////////////// u8 GetChinaCalendar(u16 year,u8 month,u8 day,u8 *p) { u8 temp1,temp2,temp3,month_p,yearH,yearL; u8 flag_y; unsigned short temp4,table_addr; yearH=year/100; yearL=year%100;//年份的高低两个字节 if((yearH!=19)&&(yearH!=20))return(0);//日期不在19xx ~ 20xx 范围内,则退出 // 定位数据表地址 if(yearH==20) table_addr=(yearL+100-1)*3; else table_addr=(yearL-1)*3; // 取当年春节所在的公历月份 temp1=year_code[table_addr+2]&0x60; temp1>>=5; // 取当年春节所在的公历日 temp2=year_code[table_addr+2]&31; // 计算当年春年离当年元旦的天数,春节只会在公历1月或2月 if(temp1==1) temp3=temp2-1; else temp3=temp2+31-1; // 计算公历日离当年元旦的天数 if (month<10) temp4=day_code1[month-1]+day-1; else temp4=day_code2[month-10]+day-1; // 如果公历月大于2月并且该年的2月为闰月,天数加1 if ((month>2)&&(yearL%4==0)) temp4++; // 判断公历日在春节前还是春节后 if (temp4>=temp3) { temp4-=temp3; month=1; month_p=1; flag_y=0; if(GetMoonDay(month_p,table_addr)==0) temp1=29; //小月29天 else temp1=30; //大小30天 // 从数据表中取该年的闰月月份,如为0则该年无闰月 temp2=year_code[table_addr]/16; while(temp4>=temp1) { temp4-=temp1; month_p++; if(month==temp2) { flag_y=~flag_y; if(flag_y==0)month++; } else month++; if(GetMoonDay(month_p,table_addr)==0) temp1=29; else temp1=30; } day=temp4+1; } // 公历日在春节前使用下面代码进行运算 else { temp3-=temp4; if (yearL==0) { yearL=100-1; yearH=19; } else yearL--; table_addr-=3; month=12; temp2=year_code[table_addr]/16; if (temp2==0) month_p=12; else month_p=13; flag_y=0; if(GetMoonDay(month_p,table_addr)==0) temp1=29; else temp1=30; while(temp3>temp1) { temp3-=temp1; month_p--; if(flag_y==0) month--; if(month==temp2) flag_y=~flag_y; if(GetMoonDay(month_p,table_addr)==0) temp1=29; else temp1=30; } day=temp1-temp3+1; } *p++=yearH; *p++=yearL; *p++=month; *p=day; return(1); } 2、触摸屏任务:处理触摸屏按键任务,更改要查询的年月日。 static void AppTaskKbd (void *p_arg) { (void)p_arg; TP_Init(); //触摸初始化 while(1) { OSTimeDlyHMSM(0,0,0,10); GUI_TOUCH_Exec(); //触摸执行程序,详细请阅读ucgui教程 } } 3、秒更新任务:秒更新任务中一直等待一个OS_EVENT(信号量),RTC闹钟一秒钟中断一次,闹钟中断程序中发送信号量,秒更新任务接到OS_EVENT(信号量)便执行一次,更新当前的时间。(如果没有不用uCOS中的信号量的话,直接设置一个全局变量也可,在中断函数中将其置1,秒更新任务中判断其为1执行,然后将其置零,等待下一次为1。 void Clock_Updata(void *p_arg) { INT8U err; (void)p_arg; while(1) { OSSemPend(Clock_SEM,0,&err); //等待 时钟更新信号量 RTC_Get(RTC_GetCounter()); } } void RTC_Get(uint32_t TimeVar) { //根据RTC时钟得到时钟的初值,注意,这个值是根据系统自动变化 to_tm(TimeVar, &systmtime); //使用野火RTC例程中的date.c } //时间结构体 struct rtc_time { int tm_sec; int tm_min; int tm_hour; int tm_mday; int tm_mon; int tm_year; int tm_wday; }; //RTC计数转化为年月日时分秒,储存在systmtime void to_tm(u32 tim, struct rtc_time * tm) { register u32 i; register long hms, day; day = tim / SECDAY; //#define SECDAY 86400L 得到天数 hms = tim % SECDAY; //余下的为时分秒 /* Hours, minutes, seconds are easy */ tm->tm_hour = hms / 3600; //时 tm->tm_min = (hms % 3600) / 60; //分 tm->tm_sec = (hms % 3600) % 60; //秒 /* Number of years in days */ /*算出当前年份,起始的计数年份为1970年,总天数减去从1970开始递增的每年天数,当天数小于365/366时,得到当前的年份*/ for (i = STARTOFTIME; day >= days_in_year(i); i++) //#define STARTOFTIME 1970 { day -= days_in_year(i); //#define days_in_year(a) (leapyear(a) ? 366 : 365) } .//#define leapyear(year) ((year) % 4 == 0) tm->tm_year = i; /* Number of months in days left */ /*计算当前的月份*/ if (leapyear(tm->tm_year)) //如果为闰年,二月为29天 { days_in_month(FEBRUARY) = 29; //#define FEBRUARY 2 } for (i = 1; day >= days_in_month(i); i++) //剩下的总天数减去从1月开始递增的每月天数,当天数小于当前月天数时,得到当前的月份。 { //static int month_days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; day -= days_in_month(i); //#define days_in_month(a) (month_days[(a) - 1]) } days_in_month(FEBRUARY) = 28; //还原二月的天数为28天 tm->tm_mon = i; /* Days are what is left over (+1) from all that. *//*计算当前日期*/ tm->tm_mday = day + 1; //剩下的天数加一为日。 /* * Determine the day of week */ GregorianDay(tm); } /*得到星期几*/ void GregorianDay(struct rtc_time * tm) { int leapsToDate; int lastYear; int day; int MonthOffset[] = { 0,31,59,90,120,151,181,212,243,273,304,334 }; lastYear=tm->tm_year-1; /*计算从公元元年到计数的前一年之中一共经历了多少个闰年*/ leapsToDate = lastYear/4 - lastYear/100 + lastYear/400; /*如若计数的这一年为闰年,且计数的月份在2月之后,则日数加1,否则不加1*/ if((tm->tm_year%4==0) &&((tm->tm_year%100!=0) || (tm->tm_year%400==0)) && (tm->tm_mon>2)) { day=1; } else { day=0; } day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] + tm->tm_mday; /*计算从公元元年元旦到计数日期一共有多少天*/ tm->tm_wday=day%7; //得到今天为星期几 } 附件:附件:UU_Clock_TOUCH.rar2013-08-260 0 3843
-
如题 由于STM32F10x库官方采用的是默认的外接8MHz晶振,因此造成很多用户也采用了8MHz的晶振,但是,8MHz的晶振不是必须的,其他频点的晶振也是可行的,只需要在库中做相应的修改就行。 在论坛上看到很多用户反映,使用外接12MHz的晶振,会造成很多的问题,如USART的波特率不正确,Systick走时不准等问题,在无论是在实际调试还是在软件模拟中都会发现这个情况,其实,这不能怪ST官方,我们必须肯定ST官方为方便用户开发所做的努力,下面我们就通过简单的三个步骤就可以让你随意的使用4—16MHz之内任何频点的晶振,我们以STM32F10x_StdPeriph_Lib_V3.4.0为例说明。 第一步,打开stm32f10x.h,将 #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ 修改为: #define HSE_VALUE ((uint32_t)12000000) /*!< Value of the External oscillator in Hz */ 第二步,打开system_stm32f10x.c,修改PLL参数,将 /* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL)); RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9); 修改为: /* PLL configuration: PLLCLK = HSE * 6 = 72 MHz */ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL)); RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL6); 至此,原文件已经修改完成,如果你想将主频修改至其他频率,请自行修改。但是,到现在,如果您直接编译调试的话,就会出现上文所说的USART的波特率不正确,Systick走时不准等问题,原因就是我们需要进行第三部的修改,这个修改不是在原文件中,而是在编译环境中。我们已Keil MDK为例说明。 第三步,打开你已经建立的STM32工程,选择Projects-〉Options for target ***,找到Target标签,你会发现,外接的晶振默认还是8MHz,我们将外接的晶振参数修改为12MHz,确定保存,再编译,调试,你就会发现,所有的参数都回归的正常轨道,设置波特率为9600,它也不会跑到14400,设置Systick为1ms中断,它不会1.5ms中断。 现在,我们也得出了一个结论,在keil MDK编译环境的设置参数的优先级是高于原文件中的设置的。2013-08-260 0 3175
-
IAR版的STM32 3.5.0库应用例子,可能对有些朋友有用,编译器的版本为V5.30 附件:led.rar 附件:Timer Uart.rar2013-08-260 0 2767
-
本帖最后由 ljc2010 于 2013-8-26 00:47 编辑 1.《MSP430系列超低功耗16位单片机原理与应用》 2.《MSP430系列FLASH型超低功耗16位单片机》 附件:MSP430系列FLASH型超低功耗16位单片机_胡大可.part1.rar 3.《MSP430系列单片机接口技术及系统设计实例》 附件:MSP430系列单片机接口_技术及系统设计实例_魏小龙.part1.rar 附件:MSP430系列单片机接口_技术及系统设计实例_魏小龙.part2.rar 附件:MSP430系列单片机接口_技术及系统设计实例_魏小龙.part3.rar 4.《MSP430系列单片机C语言程序设计与开发》 附件:MSP430系列单片机C语言程序设计与开发_胡大可.part1.rar 附件:MSP430系列单片机C语言程序设计与开发_胡大可.part2.rar 附件:MSP430系列单片机C语言程序设计与开发_胡大可.part3.rar 5.《MSP430系列16位超低功耗单片机原理与应用》 6.《MSP430系列单片机实用C语言程序设计》 附件:《MSP430系列单片机实用C语言程序设计》一书附带程序.rar 附件:MSP430系列单片机实用C语言程序设计_张晞.part1.rar 7.《MSP430单片机C语言应用程序设计实例精讲》 附件:MSP430单片机C语言应用程序设计实例精讲(秦龙).part1.rar 8.《MSP430单片机应用系统开发典型实例》 附件:MSP430单片机应用系统开发典型实例.part1.rar 附件:MSP430单片机应用系统开发典型实例.part2.rar2013-08-258 0 4691
-
恭喜南京邮电大学加入Ebaina、 论坛有你们更精彩、、2013-08-257 0 2829
-
原帖地址:[url=http://www.amobbs.com/thread-5532126-1-1.html]点击此处[/url] [postbg]bg9.png[/postbg]2013-08-250 0 2445
-
这是我自己写的关于pid的一个位置式算法的部分,在处理程序中用了比较简单的单纯的返回一个值,可以根据自己的需要改写一下。。。 定义PID结构体,包含了计算中用到的各种变量 =====================================================================================================*/ typedef struct PID { double SetPoint; // 设定目标值r(t) Desired Value double Proportion; // 比例常数k(p) Proportional Const double Integral; // 积分常数k(i) Integral Const double Derivative; // 微分常数k(d) Derivative Const double LastError; // 微分部分的 最新偏差e(k) Error[-1] double PrevError; // 微分部分的 最新偏差e(k-1) Error[-2] double SumError; // 积分部分的 累加偏差 Sums of Errors }PID; /*==================================================================================================== Initialize PID Structure----对定义的PID结构体类型的pp所占用的地址空间都给清零 =====================================================================================================*/ void PIDInit(PID *pp) { memset ( pp,0,sizeof(PID)); } /*==================================================================================================== PID计算部分----位置式PID算法 =====================================================================================================*/ double PIDCalc( PID *pp, double NextPoint ) { double dError, Error; Error = pp->SetPoint - NextPoint; // 比例部分的 最新一次采样计算的偏差 pp->SumError += Error; // 积分部分的 所有偏差的累加 dError = pp->LastError - pp->PrevError; // 微分部分的 最新一次偏差和前一次偏差的减法计算 pp->PrevError = pp->LastError; // 微分部分的 更新上一次偏差为最新偏差 pp->LastError = Error; // 微分部分的 更新最新偏差为当前偏差 return (pp->Proportion * Error + pp->Integral * pp->SumError + pp->Derivative * dError); // 比例项部分 + 积分项部分 + 微分项部分 } /*==================================================================================================== PID计算部分----增量式PID算法 =====================================================================================================*/ double PIDCalc_delt( PID *pp, double NextPoint ) { double dError, Error; Error = pp->SetPoint - NextPoint; // 比例部分的 最新一次采样计算的偏差 dError= pp->Proportion * Error + pp->Integral * pp->LastError + pp->Derivative * pp->PrevError; pp->PrevError = pp->LastError; // 微分部分的 更新上一次偏差为最新偏差 pp->LastError = Error; return (dError); } /*==================================================================================================== PID计算部分----PID处理部分 =====================================================================================================*/ uint32_t actuator(double rDelta) // Dummy Actuator Function 根据计算结果u进行处理 { return 0; }2013-08-250 0 4018
-
本破解方法是采用 IAR Embedded Workbench for ARM 6.50.2 的 破解方法,已经成功了, 申明:禁止作为商业用途,仅供学习与交流!!! [url=http://www.amobbs.com/forum.php?mod=attachment&aid=MTAyMTQ2fDM3YjI0NDc3fDEzNzczOTY4ODd8MTMyMTMwMHw1NTI3NDIy]压缩卷1[/url] [url=http://www.amobbs.com/forum.php?mod=attachment&aid=MTAyMTQ4fGE4ODhiN2EwfDEzNzczOTY4ODd8MTMyMTMwMHw1NTI3NDIy]压缩卷2[/url] [url=http://www.amobbs.com/forum.php?mod=attachment&aid=MTAyMTQ5fDA0OWFkNDdkfDEzNzczOTY4ODd8MTMyMTMwMHw1NTI3NDIy]压缩卷3[/url] [url=http://www.amobbs.com/forum.php?mod=attachment&aid=MTAyMTUwfDA2M2JjMDBjfDEzNzczOTY4ODd8MTMyMTMwMHw1NTI3NDIy]压缩卷4[/url] 注意:下载四个压缩文件后再解压,里面有操作说明!!祝大神们成功!!!!!!!!!2013-08-253 0 4248
-
/*************************************************** 本人最近开发一个项目,用到以KS0108为控制芯片的12864点阵LCD液晶模块, 为加快开发进度,本人想到网上找该模块的STM32程序,可是找了好久,没有找到, 只能自己写,这些子程序是本人调试通过的,本程序适用于以KS0108或兼容芯片为 控制器的双屏结构的液晶模块,项目还没做完,先把子程序分享给大家,仅供参考...... ****************************************************/ #include "stm32f10x.h" #define LCD_E1 GPIOC->BSRR = GPIO_Pin_12 //PC12 #define LCD_E0 GPIOC->BRR = GPIO_Pin_12 #define LCD_DI1 GPIOG->BSRR = GPIO_Pin_13 //PG #define LCD_DI0 GPIOG->BRR = GPIO_Pin_13 #define LCD_RW1 GPIOE->BSRR = GPIO_Pin_4 //PE4 #define LCD_RW0 GPIOE->BRR = GPIO_Pin_4 #define LCD_RST1 GPIOG->BSRR = GPIO_Pin_12 //PG12 #define LCD_RST0 GPIOG->BRR = GPIO_Pin_12 #define LCD_CS11 GPIOC->BSRR = GPIO_Pin_10 //PC10 #define LCD_CS10 GPIOC->BRR = GPIO_Pin_10 #define LCD_CS21 GPIOC->BSRR = GPIO_Pin_11 //PC11 #define LCD_CS20 GPIOC->BRR = GPIO_Pin_11 #define LCD_PORT GPIOD #define LCD_DISP_ON 0x3F #define LCD_DISP_OFF 0x3E #define LCD_DISP_ROW 0xC0 #define LCD_DISP_PAGE 0xB8 #define LCD_DISP_Y 0x40 GPIO_InitTypeDef GPIO_InitStructure; void Delayms(uint32_t ms) { //uint32_t temp; uint32_t i, j; for( i = ms; i > 0; i-- ) { for( j = 7200 ; j > 0 ; j-- ) {} } } void LCD_Configuration(void) { GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7 ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(LCD_PORT, &GPIO_InitStructure); // PORTD 为开漏输出 GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOE, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_12|GPIO_Pin_13); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOG, &GPIO_InitStructure); Delayms(1); } void LCD_reset(void) { LCD_E0; Delayus(10); LCD_RST0; Delayms(2); LCD_RST1; Delayms(200); } void LCD_CS(u8 index) //0--select none 1--left 2--right 3--all { switch(index) { case 0: LCD_CS11; LCD_CS21; break; case 1: LCD_CS10; LCD_CS21; break; case 2: LCD_CS11; LCD_CS20; break; case 3: LCD_CS10; LCD_CS20; break; } Delayus(100); } void LCD_Check_Busy(void) { //GPIO_InitTypeDef GPIO_InitStructure; u8 temp=0; LCD_DI0; // DI =0 指令 LCD_RW1; // RW =1 读模式 // 第7位读状态 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(LCD_PORT, &GPIO_InitStructure); Delayus(1); do{ LCD_E1; Delayus(1); temp = GPIO_ReadInputDataBit(LCD_PORT, GPIO_Pin_7); LCD_E0; Delayus(1); }while(temp);//等待不忙 LCD_E0; //--------把D7 设为输出 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(LCD_PORT, &GPIO_InitStructure); Delayus(1); //--------------------- } void LCD_cmd(vu8 portValue) { u16 tmpData; LCD_Check_Busy(); LCD_RW0; LCD_DI0; tmpData = GPIO_ReadOutputData(LCD_PORT); // 读端口数据 tmpData &= 0xFF00; // 清掉低8位 GPIO_Write(LCD_PORT, (tmpData|((u16)portValue))); Delayus(1); LCD_E1; Delayus(1); LCD_E0; Delayus(1); } vu8 LCD_rd(void)//在写地址后,要进行一次空读,以后每读一次地址自动加1 { vu8 rdata; LCD_Check_Busy(); //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; //低8位输入 GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7 ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(LCD_PORT, &GPIO_InitStructure); LCD_RW1; //READ LCD_DI1; //DATA Delayus(1); LCD_E1; Delayus(5); rdata=GPIO_ReadInputData(LCD_PORT); LCD_E0; Delayus(1); //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7 ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; //GPIO_InitStructure.GPIO_Pin =0x00FF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(LCD_PORT, &GPIO_InitStructure); Delayus(1); return rdata; } void LCD_wd(vu8 portValue) { u16 tmpData; LCD_Check_Busy();//LEFT OR RIGHT LCD_RW0; //WRITE LCD_DI1; //DATA tmpData = GPIO_ReadOutputData(LCD_PORT); // 读端口数据 tmpData &= 0xFF00; // 清掉低8位 GPIO_Write(LCD_PORT,(tmpData|((u16)portValue))); // 写数据到端口 Delayus(1); LCD_E1; Delayus(1); LCD_E0; Delayus(1); } void LCD_rwd(u8 row,u8 page,u8 dat,u8 mode)//读修改写模式 page 0~7 row 0~127 { vu8 rd; if(row<64) { LCD_CS(1); LCD_cmd(LCD_DISP_PAGE+page); //定位页 LCD_cmd(LCD_DISP_Y+row);//定位列 rd=LCD_rd();//空读 rd=LCD_rd(); LCD_cmd(LCD_DISP_PAGE+page); //定位页 LCD_cmd(LCD_DISP_Y+row);//定位列 if(mode==0) LCD_wd(dat); else if(mode==1) LCD_wd(dat|rd);//或模式 else if(mode==2) LCD_wd(dat&rd);//与模式 else LCD_wd(~rd);//取反 } else { LCD_CS(2); LCD_cmd(LCD_DISP_PAGE+page); //定位页 LCD_cmd(LCD_DISP_Y+row-64);//定位列 rd=LCD_rd();//空读 rd=LCD_rd(); LCD_cmd(LCD_DISP_PAGE+page); //定位页 LCD_cmd(LCD_DISP_Y+row-64);//定位列 if(mode==0) LCD_wd(dat); else if(mode==1) LCD_wd(dat|rd);//或模式 else if(mode==2) LCD_wd(dat&rd);//与模式 else LCD_wd(~rd);//取反 } } void LCD_init() { LCD_CS(3);//选左屏 右屏 LCD_cmd(LCD_DISP_PAGE);//0xb8 Delayms(5); LCD_cmd(LCD_DISP_Y); //0x40 Delayms(5); LCD_cmd(LCD_DISP_ROW);//START LINE 0xc0 Delayms(5); LCD_cmd(LCD_DISP_ON); //0x3f Delayms(5); } void LCD_Clear(void) { u8 page,count; for(page=0xb8;page<=0xbF;page++)//共8 页,0XB8-0XBF { LCD_cmd(page); LCD_cmd(0x40); for(count=64;count>0;count--)//写第page 页的左64 列 { LCD_wd(0X00); } } } void LCD_Pixe(u8 x,u8 y)//画点程序 { /* vu8 rd; if(x<64) { LCD_CS(1); LCD_cmd(LCD_DISP_PAGE+y/8); //定位页 LCD_cmd(LCD_DISP_Y+x);//定位列 rd=LCD_rd();//空读 rd=LCD_rd(); LCD_cmd(LCD_DISP_PAGE+y/8); //定位页 LCD_cmd(LCD_DISP_Y+x);//定位列 LCD_wd((1<<(y%8))|rd); } else { LCD_CS(2); LCD_cmd(LCD_DISP_PAGE+y/8); //定位页 LCD_cmd(LCD_DISP_Y+x-64);//定位列 rd=LCD_rd();//空读 rd=LCD_rd(); LCD_cmd(LCD_DISP_PAGE+y/8); //定位页 LCD_cmd(LCD_DISP_Y+x-64);//定位列 LCD_wd((1<<(y%8))|rd); } */ LCD_rwd(x,y/8,(1<<(y%8)),1); } //画横线程序 void LCD_H_Line(u8 x1,u8 y1, u8 len,u8 weight) //len 0~128 { u8 i,p,dat,xx; p=y1/8; dat=((1< for(i=0;i { xx=x1+i; if(xx>127) xx=127;//超过屏幕边沿剪断 LCD_rwd(xx,p,dat,1); } } //画坚线程序 void LCD_V_Line(u8 x1,u8 y1,u8 len,u8 weight) //len 0~64 { u8 i,j,p,xx,yy,dat=0; for(j=0;j { for(i=0;i { yy=y1+i; if(yy>63) yy=63;//超过屏幕边沿剪断 p=yy/8; dat|=(1<<(yy%8));// if((yy+1)%8==0||(i==len)); { xx=x1+j; if(xx>127) xx=127;//超过屏幕边沿剪断 LCD_rwd(xx,p,dat,1); dat=0; } } } }2013-08-251 0 4072
-
本帖最后由 495005638 于 2013-8-25 10:06 编辑 开发板stm3210e-eval对应芯片型号是stm32f103zet6 stm3210b-eval对应芯片型号是stm32f103vbt6 所建工程默认为stm32f103zet6 几乎stm32所有的例程都有,包括很多开发板忽略实际工作中常用到的到低功耗例程,尤其是在电池供电系统中 stm32 GPIO,USART,RCC,PWR,NVIC,SysTick,EXTI,RTC,I2C,I2S,TIM,WWDG,IWDG,DMA,SPI,SDIO,CRC,DAC,DMA,FLASH,CAN,BKP,ADC 分类代码图: 附件:86个测试程序.part1.rar附件:86个测试程序.part2.rar2013-08-243 0 4570
-
本帖最后由 495005638 于 2013-8-24 22:59 编辑 刚刚画了一个STM32F103ZET6的PCB封装集成库,用altium designer 10画的,希望对大家有用。对于PCB管脚的尺寸稍微延长了一点,适合手工焊接,不知合不合适,欢迎指正。2013-08-241 0 3262
-
STM32 USB HID开发实例,实现USB双向通信。 在STM32 ARM平台上实现USB与PC端得通信(IC为STM32F10XX系列)。本文提供一个例程(已测试通过),不用了解任何USB协议(当然了解USB相关协议或描述表的意义是很必要的),在此例程上,稍作修改,即可开展你的项目或学习或进行产品开发。 在ST中我们可以获得了USB相关的一个HID例程,但是官方例子中只是用到2个端点。数据只收不发。 本例程中,用到了3个USB端点,实现PC上位机与下位机见双向通信。EP0为控制端点(必须的,这是因为系统默认端点0作为控制传输端点),EP1为INTERRUPT OUT端点(数据输出端,即PC向MCU发送数据段),EP2为INTERRUPT OUT端点(数据输入端,即MCU向PC发送数据)。 实现过程,我们需要修改一下HID的描述表,修改如下(有详细注释) /* USB Configuration Descriptor */ /* All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */ const u8 CustomHID_ConfigDescriptor[CUSTOMHID_SIZ_CONFIG_DESC] = { 0x09, /* bLength: Configuation Descriptor size */ USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */ CUSTOMHID_SIZ_CONFIG_DESC, /* wTotalLength: Bytes returned */ 0x00, 0x01, /* bNumInterfaces: 1 interface */ 0x01, /* bConfigurationValue: Configuration value */ 0x00, /* iConfiguration: Index of string descriptor describing the configuration*/ 0xC0, /* bmAttributes: Bus powered */ /*Bus powered: 7th bit, Self Powered: 6th bit, Remote wakeup: 5th bit, reserved: 4..0 bits */ 0x32, /* MaxPower 100 mA: this current is used for detecting Vbus */ // 0x96, /* MaxPower 300 mA: this current is used for detecting Vbus */ /************** Descriptor of Custom HID interface ****************/ /* 09 */ 0x09, /* bLength: Interface Descriptor size */ USB_INTERFACE_DESCRIPTOR_TYPE,/* bDescriptorType: Interface descriptor type */ 0x00, /* bInterfaceNumber: Number of Interface */ 0x00, /* bAlternateSetting: Alternate setting */ 0x02, /* bNumEndpoints */ 0x03, /* bInterfaceClass: HID */ 0x00, /* bInterfaceSubClass : 1=BOOT, 0=no boot */ 0x00, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */ 0, /* iInterface: Index of string descriptor */ /******************** Descriptor of Custom HID HID ********************/ /* 18 */ 0x09, /* bLength: HID Descriptor size */ HID_DESCRIPTOR_TYPE, /* bDescriptorType: HID */ 0x10, /* bcdHID: HID Class Spec release number */ 0x01, 0x00, /* bCountryCode: Hardware target country */ 0x01, /* bNumDescriptors: Number of HID class descriptors to follow */ 0x22, /* bDescriptorType */ CUSTOMHID_SIZ_REPORT_DESC,/* wItemLength: Total length of Report descriptor */ 0x00, /******************** Descriptor of Custom HID endpoints ******************/ /* 27 */ 0x07, /* bLength: Endpoint Descriptor size */ USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: */ 0x82, /* bEndpointAddress: Endpoint Address (IN) */ // bit 3...0 : the endpoint number // bit 6...4 : reserved // bit 7 : 0(OUT), 1(IN) 0x03, /* bmAttributes: Interrupt endpoint */ 0x40,//0x02, /* wMaxPacketSize: 20 Bytes max */ 0x00, 0x20, /* bInterval: Polling Interval (32 ms) */ /* 34 */ 0x07, /* bLength: Endpoint Descriptor size */ USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: */ /* Endpoint descriptor type */ 0x01, /* bEndpointAddress: */ /* Endpoint Address (OUT) */ 0x03, /* bmAttributes: Interrupt endpoint */ 0x40,//0x02, /* wMaxPacketSize: 20 Bytes max */ 0x00, 0x10, /* bInterval: Polling Interval (16 ms) */ /* 41 */ }; /* CustomHID_ConfigDescriptor */ 关于如何理解HID 描述表,请参考USB HID协议1.1版本,相关资料可以在网络上搜索得到。 在此,现提供KEIL MDK 和 IAR EWARM 5.4版本的例子,欢迎下载。萝卜青菜,喜欢用MDK,就MDK,喜欢EWARM,就EWARM。同样这里有见有意思的事,在全编译的情况下,EWARM要比MDK编译速度要快一些。2013-08-240 0 4886
-
如题、 上传本人觉得不错的6050的资料,分享给需要的友友们、 附件:MPU-60X0寄存器中文版V4.0.pdf2013-08-240 0 3102

共22条
- 1
- 2