正点原子

个性签名:我的淘宝:http://shop62103354.taobao.com

    1. stm32+dm9000网络专题 143/23777 stm32/stm8 2015-02-06
      学习下。谢谢分享
    2. hanskying666 发表于 2014-11-8 23:20 很不错,F4强大的处理能力!
      是的,软件视频。
    3. dcexpert 发表于 2014-11-8 22:51 内容很丰富。
      恩,搞了差不多一年了,呵呵。
    4. 另外,内存管理,不一定要外部扩展ram,单独的stm32自己内存都够用了。
    5. 我们的图片编解码都是用的内存管理实现,还有fatfs也是。 你不用的话,这些地方都得修改一下。
    6. 死机了。
    7. int main(void){                 Stm32_Clock_Init(9);    //系统时钟设置       uart_init(72,9600);      //串口初始化为9600       delay_init(72);                  //延时初始化       LED_Init();                 //初始化与LED连接的硬件接口       LCD_Init();                  //初始化LCD       usmart_dev.init(72);      //初始化USMART       BEEP_Init();                //蜂鸣器初始化           KEY_Init();                  //按键初始化       TPAD_Init(72);             //初始化TPAD      FSMC_SRAM_Init();    //初始化外部SRAM       mem_init(SRAMIN);     //初始化内部内存池       mem_init(SRAMEX);    //初始化外部内存池     tp_dev.init();       ucos_load_main_ui();       OSInit();                           //初始化UCOSII      OSTaskCreate(start_task,(void *)0,(OS_STK *)&START_TASK_STK[START_STK_SIZE-1],START_TASK_PRIO );//创建起始任务       OSStart();         }                           //开始任务void start_task(void *pdata){    OS_CPU_SR cpu_sr=0; u8 err;                                  pdata = pdata;             msg_key=OSMboxCreate((void*)0);    //创建消息邮箱       q_msg=OSQCreate(&MsgGrp[0],256); //创建消息队列      flags_key=OSFlagCreate(0,&err);       //创建信号量集                    OSStatInit();                                      //初始化统计任务.这里会延时1秒钟左右      OS_ENTER_CRITICAL();                  //进入临界区(无法被中断打断)         OSTaskCreate(led_task,(void *)0,(OS_STK*)&LED_TASK_STK[LED_STK_SIZE-1],LED_TASK_PRIO);                                                 OSTaskCreate(touch_task,(void *)0,(OS_STK*)&TOUCH_TASK_STK[TOUCH_STK_SIZE-1],TOUCH_TASK_PRIO);                                          OSTaskCreate(qmsgshow_task,(void *)0,(OS_STK*)&QMSGSHOW_TASK_STK[QMSGSHOW_STK_SIZE-1],QMSGSHOW_TASK_PRIO);                                       OSTaskCreate(main_task,(void *)0,(OS_STK*)&MAIN_TASK_STK[MAIN_STK_SIZE-1],MAIN_TASK_PRIO);                                        OSTaskCreate(flags_task,(void *)0,(OS_STK*)&FLAGS_TASK_STK[FLAGS_STK_SIZE-1],FLAGS_TASK_PRIO);                                     OSTaskCreate(key_task,(void *)0,(OS_STK*)&KEY_TASK_STK[KEY_STK_SIZE-1],KEY_TASK_PRIO);                                       OSTaskSuspend(START_TASK_PRIO);       //挂起起始任务.       OS_EXIT_CRITICAL();                            //退出临界区(可以被中断打断)}//LED任务void led_task(void *pdata){       u8 t;       while(1)       {              t++; delay_ms(10);              if(t==8)LED0=1;                 //LED0灭              if(t==100) {t=0; LED0=0; }  //LED0亮                   }                                                            }//触摸屏任务void touch_task(void *pdata){                 while(1)       {              tp_dev.scan(0);                            if(tp_dev.sta&TP_PRES_DOWN)        //触摸屏被按下              {                        if(tp_dev.x
    8. 图来了
    9. 这里,我们需要了解uIP是把网页数据(源文件)存放在data_index_html,通过将这里面的数据发送给电脑浏览器,浏览器就会显示出我们所设计的界面了。当用户在网页上面操作的时候,浏览器就会发送消息给WEB服务器,服务器根据收到的消息内容,判断用户所执行的操作,然后发送新的页面到浏览器,这样用户就可以看到操作结果了。本章,我们实现的WEB服界面如图57.3.2所示:http://file:///C:/Documents%20and%20Settings/Administrator/桌面/论坛推广/第57章/新建%20Microsoft%20Word%20文档.files/image009.png图57.3.2 WEB服务器界面图中两个按键分别控制DS0和DS1的亮灭,然后还显示了STM32芯片的温度和RTC时间等信息。 控制DS0,DS1亮灭我们是通过发送不同的页面请求来实现的,这里我们采用的是Get方法(科普找百度),将请求参数放到URL里面,然后WEB服务器根据URL的参数来相应内容,这样实际上STM32就是从URL获取控制参数,以控制DS0和DS1的亮灭。uIP在得到Get请求后判断URL内容,然后做出相应控制,最后修改data_index_html里面的部分内容(比如指示灯图标的变化,以及提示文字的变化等),再将data_index_html发送给浏览器,显示新的界面。显示STM32温度和RTC时间是通过刷新实现的,uIP每次得到来自浏览器的请求就会更新data_index_html里面的温度和时间等信息,然后将data_index_html发送给浏览器,这样达到更新温度和时间的目的。但是这样我们需要手动刷新,比较笨,所以我们在网页源码里面加入了自动刷新的控制代码,每10秒钟刷新一次,这样就不需要手动刷新了。handle_input函数实现了我们所说的这一切功能,另外请注意data_index_html是存放在httpd-fsdata.c(该文件通过include的方式包含进工程里面)里面的一个数组,并且由于该数组的内容需要不停的刷新,所以我们定义它为sram数据,data_index_html里面的数据,则是通过一个工具软件:amo的编程小工具集合V1.2.6.exe,将网页源码转换而来,该软件在光盘有提供,如果想自己做网页的朋友,可以通过该软件转换。WEB服务器就为大家介绍这么多。接下来看看TCP服务器appcall函数:tcp_server_demo_appcall,该函数在tcp_server_demo.c里面实现,该函数代码如下:u8 tcp_server_databuf[200];       //发送数据缓存       u8 tcp_server_sta;                        //服务端状态//[7]:0,无连接;1,已经连接;//[6]:0,无数据;1,收到客户端数据//[5]:0,无数据;1,有数据需要发送 //这是一个TCP 服务器应用回调函数。//该函数通过UIP_APPCALL(tcp_demo_appcall)调用,实现Web Server的功能.//当uip事件发生时,UIP_APPCALL函数会被调用,根据所属端口(1200),确定是否执行该函数。//例如 : 当一个TCP连接被创建时、有新的数据到达、数据已经被应答、数据需要重发等事件void tcp_server_demo_appcall(void){      struct tcp_demo_appstate *s = (struct tcp_demo_appstate *)&uip_conn->appstate;       if(uip_aborted())tcp_server_aborted();         //连接终止      if(uip_timedout())tcp_server_timedout();     //连接超时          if(uip_closed())tcp_server_closed();            //连接关闭              if(uip_connected())tcp_server_connected();  //连接成功                if(uip_acked())tcp_server_acked();                     //发送的数据成功送达        //接收到一个新的TCP数据包        if (uip_newdata())//收到客户端发过来的数据       {              if((tcp_server_sta&(1
    10. //得到角度//x,y,z:x,y,z方向的重力加速度分量(不需要单位,直接数值即可)//dir:要获得的角度.0,与Z轴的角度;1,与X轴的角度;2,与Y轴的角度.//返回值:角度值.单位0.1°.short ADXL345_Get_Angle(float x,float y,float z,u8 dir){       float temp,res=0;        switch(dir)       {              case 0://与自然Z轴的角度                    temp=sqrt((x*x+y*y))/z;                    res=atan(temp);                    break;              case 1://与自然X轴的角度                    temp=x/sqrt((y*y+z*z));                    res=atan(temp);                    break;             case 2://与自然Y轴的角度                    temp=y/sqrt((x*x+z*z));                    res=atan(temp);                    break;      }       return res*1800/3.14;} 该部分代码总共有8个函数,这里我们仅介绍其中4个。首先是ADXL345_Init函数,该函数用来初始化ADXL345,和前面我们提到的步骤差不多,不过本章我们而是采用查询的方式来读取数据的,所以在这里并没有开启中断。另外3个偏移寄存器,都默认设置为0。其次,我们介绍ADXL345_RD_XYZ函数,该函数用于从ADXL345读取数据,通过该函数可以读取ADXL345的转换结果,得到三个轴的加速度值(仅是数值,并没有转换单位)。接着,我们介绍ADXL345_AUTO_Adjust函数,该函数用于ADXL345的校准,ADXL345有偏移校准的功能,该功能的详细介绍请参考ADXL345数据手册的第29页,偏移校准部分。这里我们就不细说了,如果不进行校准的话,ADXL345的读数可能会有些偏差,通过校准,我们可以讲这个偏差减少甚至消除。最后,我们看看ADXL345_Get_Angle函数,该函数根据ADXL345的读值,转换为与自然坐标系的角度。计算公式如下: 其中Ax,Ay,Az分别代表从ADXL345读到的X,Y,Z方向的加速度值。通过该函数,我们只需要知道三个方向的加速度值,就可以将其转换为对应的弧度值,再通过弧度角度转换,就可以得到角度值了。其他函数,我们就不介绍了,也比较简单。保存adxl345.c,然后把该文件加入HARDWARE组下。接下来打开adxl345.h在该文件里面加入如下代码:#ifndef __ADXL345_H#define __ADXL345_H#include "myiic.h"   #define DEVICE_ID            0X00      //器件ID,0XE5#define THRESH_TAP         0X1D          //敲击阀值……省略部分寄存器定义#define FIFO_STATUS         0X39 //0X0B TO OX1F Factory Reserved     //如果ALT ADDRESS脚(12脚)接地,IIC地址为0X53(不包含最低位).//如果接V3.3,则IIC地址为0X1D(不包含最低位).//开发板接V3.3,所以转为读写地址后,为0X3B和0X3A(如果接GND,则为0XA7和0XA6)  #define ADXL_READ    0X3B#define ADXL_WRITE   0X3Au8 ADXL345_Init(void);                                                              //初始化ADXL345void ADXL345_WR_Reg(u8 addr,u8 val);                                      //写ADXL345寄存器u8 ADXL345_RD_Reg(u8 addr);                                                   //读ADXL345寄存器void ADXL345_RD_XYZ(short *x,short *y,short *z);                      //读取一次值void ADXL345_RD_Avval(short *x,short *y,short *z);                    //读取平均值void ADXL345_AUTO_Adjust(char *xval,char *yval,char *zval);     //自动校准void ADXL345_Read_Average(short *x,short *y,short *z,u8 times);//连续读取times次,取平均short ADXL345_Get_Angle(float x,float y,float z,u8 dir);#endif上面的代码省略了部分寄存器的定义,其他部分比较简单,我们不作介绍。保存adxl345.h,然后在test.c里面修改代码如下://x,y:开始显示的坐标位置//num:要显示的数据//mode:0,显示加速度值;1,显示角度值;void Adxl_Show_Num(u16 x,u16 y,short num,u8 mode){       if(mode==0)   //显示加速度值       {              if(num
    11. 30.3 软件设计 打开上一章的工程,首先在HARDWARE文件夹下新建一个CAN的文件夹,然后新建一个can.c和can.h的文件保存在CAN文件夹下,并将CAN文件夹加入头文件包含路径。打开can.c文件,输入如下代码:#include "can.h"#include "led.h"#include "delay.h"#include "usart.h"//CAN初始化//tsjw:重新同步跳跃时间单元.范围:1~3;//tbs2:时间段2的时间单元.范围:1~8;//tbs1:时间段1的时间单元.范围:1~16;//brp :波特率分频器.范围:1~1024;(实际要加1,也就是1~1024) tq=(brp)*tpclk1//注意以上参数任何一个都不能设为0,否则会乱.//波特率=Fpclk1/((tbs1+tbs2+1)*brp);//mode:0,普通模式;1,回环模式;//Fpclk1的时钟在初始化的时候设置为36M,如果设置CAN_Normal_Init(1,8,7,5,1);//则波特率为:36M/((8+7+1)*5)=450Kbps//返回值:0,初始化OK;//    其他,初始化失败;u8 CAN_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode){       u16 i=0;      if(tsjw==0||tbs2==0||tbs1==0||brp==0)return 1;       tsjw-=1;//先减去1.再用于设置       tbs2-=1;       tbs1-=1;       brp-=1;       RCC->APB2ENR|=1CRH|=0X000B8000;//PA11 RX,PA12 TX推挽输出             GPIOA->ODR|=3>16)&0XFF;       dat[7]=(CAN->sFIFOMailBox[fifox].RDHR>>24)&0XFF;         if(fifox==0)CAN->RF0R|=0X20;//释放FIFO0邮箱       else if(fifox==1)CAN->RF1R|=0X20;//释放FIFO1邮箱  }#if CAN_RX0_INT_ENABLE      //使能RX0中断//中断服务函数                      void USB_LP_CAN1_RX0_IRQHandler(void){       u8 rxbuf[8];       u32 id;       u8 ide,rtr,len;          Can_Rx_Msg(0,&id,&ide,&rtr,&len,rxbuf);    printf("id:%d\r\n",id);    printf("ide:%d\r\n",ide);    printf("rtr:%d\r\n",rtr);    printf("len:%d\r\n",len);    printf("rxbuf[0]:%d\r\n",rxbuf[0]);    printf("rxbuf[1]:%d\r\n",rxbuf[1]);    printf("rxbuf[2]:%d\r\n",rxbuf[2]);    printf("rxbuf[3]:%d\r\n",rxbuf[3]);    printf("rxbuf[4]:%d\r\n",rxbuf[4]);    printf("rxbuf[5]:%d\r\n",rxbuf[5]);    printf("rxbuf[6]:%d\r\n",rxbuf[6]);    printf("rxbuf[7]:%d\r\n",rxbuf[7]);}#endif //can发送一组数据(固定格式:ID为0X12,标准帧,数据帧)     //len:数据长度(最大为8)                              //msg:数据指针,最大为8个字节.//返回值:0,成功;//            其他,失败;u8 Can_Send_Msg(u8* msg,u8 len){           u8 mbox;       u16 i=0;                                                            mbox=Can_Tx_Msg(0X12,0,0,len,msg);       while((Can_Tx_Staus(mbox)!=0X07)&&(i=0XFFF)return 1;                                             //发送失败?       return 0;                                                                 //发送成功;}//can口接收数据查询//buf:数据缓存区; //返回值:0,无数据被收到;//            其他,接收的数据长度;u8 Can_Receive_Msg(u8 *buf){                                  u32 id;       u8 ide,rtr,len;       if(Can_Msg_Pend(0)==0)return 0;                     //没有接收到数据,直接退出              Can_Rx_Msg(0,&id,&ide,&rtr,&len,buf);   //读取数据    if(id!=0x12||ide!=0||rtr!=0)len=0;                //接收错误              return len;     }此部分代码总共8个函数,我们挑其中几个比较重要的函数简单介绍下,首先是:CAN_Mode_Init函数。该函数用于CAN的初始化,该函数带有5个参数,可以设置CAN通信的波特率和工作模式等,在该函数中,我们就是按30.1节末尾的介绍来初始化的,本章中,我们设计滤波器组0工作在32位标识符屏蔽模式,从设计值可以看出,该滤波器是不会对任何标识符进行过滤的,因为所有的标识符位都被设置成不需要关心,这样设计,主要是方便大家实验。    第二个函数,Can_Tx_Msg函数。该函数用于CAN报文的发送,该函数先查找空的发送邮箱,然后设置标识符ID等信息,最后写入数据长度和数据,并请求发送,实现一次报文的发送。    第三个函数,Can_Msg_Pend函数。该函数用于查询接收FIFOx(x=0/1)是否为空,如果返回0,则表示FIFOx空,如果为其他值,则表示FIFOx有数据。    第四个函数,Can_Rx_Msg函数。该函数用于CAN报文的接收,该函数先读取标识符,然后读取数据长度,并读取接收到的数据,最后释放邮箱数据。       can.c里面,还包含了中断接收的配置,通过can.h的CAN_RX0_INT_ENABLE宏定义,来配置是否使能中断接收,本章我们不开启中断接收的。其他函数我们就不一一介绍了,都比较简单,大家自行理解即可。保存can.c,并把该文件加入HARDWARE组下面,然后我们打开can.h在里面输入如下代码:#ifndef __CAN_H#define __CAN_H #include "sys.h"        //CAN接收RX0中断使能#define CAN_RX0_INT_ENABLE      0                                 //0,不使能;1,使能.       u8 CAN_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode);  //CAN初始化u8 Can_Tx_Msg(u32 id,u8 ide,u8 rtr,u8 len,u8 *dat);                //发送数据u8 Can_Msg_Pend(u8 fifox);                                                  //查询邮箱报文void Can_Rx_Msg(u8 fifox,u32 *id,u8 *ide,u8 *rtr,u8 *len,u8 *dat);//接收数据u8 Can_Tx_Staus(u8 mbox);                                                 //返回发送状态u8 Can_Send_Msg(u8* msg,u8 len);                                       //发送数据u8 Can_Receive_Msg(u8 *buf);                                              //接收数据#endif  其中CAN_RX0_INT_ENABLE用于设置是否使能中断接收,本章我们不用中断接收,故设置为0。保存can.h。最后,我们在test.c里面,修改main函数如下:int main(void){                  u8 key;       u8 i=0,t=0;       u8 cnt=0;       u8 canbuf[8];       u8 res;       u8 mode=1;//CAN工作模式;0,普通模式;1,环回模式      Stm32_Clock_Init(9);    //系统时钟设置       uart_init(72,9600);      //串口初始化为9600       delay_init(72);                  //延时初始化       LED_Init();                 //初始化与LED连接的硬件接口       LCD_Init();                  //初始化LCD       usmart_dev.init(72);      //初始化USMART              KEY_Init();                  //按键初始化                   CAN_Mode_Init(1,8,7,5,mode);//CAN初始化,波特率450Kbps         POINT_COLOR=RED;//设置字体为红色       LCD_ShowString(60,50,200,16,16,"WarShip STM32");          LCD_ShowString(60,70,200,16,16,"CAN TEST");           LCD_ShowString(60,90,200,16,16,"ATOM@ALIENTEK");       LCD_ShowString(60,110,200,16,16,"2012/9/11");       LCD_ShowString(60,130,200,16,16,"LoopBack Mode");         LCD_ShowString(60,150,200,16,16,"KEY0:Send WK_UP:Mode");//显示提示信息                  POINT_COLOR=BLUE;//设置字体为蓝色         LCD_ShowString(60,170,200,16,16,"Count:");                 //显示当前计数值        LCD_ShowString(60,190,200,16,16,"Send Data:");           //提示发送的数据        LCD_ShowString(60,250,200,16,16,"Receive Data:");              //提示接收到的数据                 while(1)       {              key=KEY_Scan(0);              if(key==KEY_RIGHT)//KEY0按下,发送一次数据              {                     for(i=0;i
    12. my style.呵呵。
    13. 谢谢支持
    14. 一篇有关哈佛的文章,让我很感慨 29/11102 工作这点儿事 2010-10-23
      央视的采访,你也信? 4点多还在学习,骗鬼啊. 你一天可以,难道你就不要休息?某非哈弗的人都用了印度神油? 用电脑子想想,别跟着央视的瞎扯淡....
    15. 团购已结束,现在只能以正常价格购买了,呵呵。
    16. 不买仿真器,肯定就仿真不了了,呵呵。 在线下载程序是可以的,我们通过USB串口下载代码,所以只要您的电脑有USB,就可以下载代码的。 关于调试,也不一定要仿真器,可以通过串口打印信息来查看运行状态,其实这样更能锻炼你的能力。
    17. 开发板的资料,将集中在这个帖子: https://bbs.eeworld.com.cn/viewt ... ge=1&extra=page%3D1 如果你有什么问题或者建议,都可以在这个帖子里面提出。
    18. 求助单片机万年历 28/13768 电子竞赛 2009-04-19
      DDDDDDDDDDDDDDDDDDDDDD
    19. 双核单片机LS2051光影棒的原理图 50/25761 DIY/开源硬件专区 2008-12-11
      电子工程师.下载还要啥币.郁闷... ================================= 我没有要芯币啊 不是免费的么
    20. 给大家一个GL850A的USB HUB的图 71/39356 单片机 2008-06-26
      拜托,HUB要什么启动,插上就行了。

统计信息

已有33108人来访过

  • 芯积分:--
  • 好友:4
  • 主题:89
  • 回复:20

留言

你需要登录后才可以留言 登录 | 注册


LANGXIA 2021-3-20
原子哥AL422B写满了继续写会怎样?
xgz 2018-8-19
原子哥,我用stm32f407加载fatfs对8G的sd卡读写成功,但换用128G的sd卡时,可以检测到sd卡,即读不了卡的大小,也写不了数据,下载fatfs0.12b版,但不会写底层程序 . . . . . .
哥不是说读写128G的sd卡没问题吗?能发个例程吗?先谢了 !!!
找到HAL库函数版,问题已解决。
梦由心生 2018-2-7
开发板中定时器中断控制IO口输出频率是正确的,但是在自己焊接的板子上频率输出为什么是不正确的
wateras1 2014-8-23
写的不错
wateras1 2014-8-23
写的不错
_Stone_ 2013-8-10
原子哥.. stm32 TIM2计数器清零失败....  发帖在阿莫了..
http://www.amobbs.com/thread-5546087-1-1.html
能不能帮忙解决一下....
googleyang123 2012-6-4
原子哥,我在做fat32的实验 FileInfo=&a ;                        temp=1;                             Get_File_Info(fcluster, FileInfo, T_FILE, &temp);        printf("\r\n File Name: %s", a .F_Name); 为什么独到的中文文件名是乱码,英文文件名正常, 但是在你的例程里可以读到中文文件名 ...
hansmmm 2012-5-24
您好!请教朋友stm32问题,朋友向我推荐您。我这里有一个困惑,还希望您能指点一下,感激不尽。例程中的can_normal程序中,在can初始化里面有一句CAN_ITConfig(CAN1,CAN_IT_FMP0, ENABLE);使能挂号中断。在NVIC中却是 NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;然后在中断服务函数中是与USB_LP_CAN1_RX0_IRQn相关的中断函数。小弟有点疑惑,CAN_IT_FMP0和USB_LP_CAN1_RX0_IRQn这两个中断的异同点是什么?在具体接收数据中又是如何相互配合工作的呢?
查看全部