最新日志

发表于:2008-4-28 15:55:50
标签:PWM  转速  m48  AVR  

0

[原创]用M48的PWM功能控制风扇转速

   比较基础简单的试验,适合新手入门老鸟就不用看了,呵呵!

   ATMega48的定时器1工作在8位快速PWM模式,产生3906.25Hz的PWM波通过三极管来调整风扇的转速,风扇是CPU散热器上的直流12V风扇。程序是循环重低到高再到低来调整风扇转速。

点击看大图

代码如下:

/*************************************************************************
* Copyright (c) 2007 wormchen            
* All rights reserved             
* 文 件 名: main.c              
* 说    明: PWM 调整风扇转速                
*                            
* 主要硬件: AtemlMega48(内部1M)            
* 编译环境: WinAVR 20070525            
* 当前版本: 1.0               
* 作    者: wormchen               
* 完成日期: 2008年4月22日11:33:19          
* 取代版本: 1.0               
* 原作  者: wormchen              
* 完成日期: 2008年4月22日11:33:23          
************************************************************************/  
#include
#include
#include
unsigned int uchPWM = 0;

/************************************************************************
* 名称: void DelayMS(unsigned int uiMS)           
* 功能: 延时nms                     
* 参数: 无                                   
* 返回: 无                                     
************************************************************************/
void DelayMS(unsigned int uiMS)
 { 
  while(uiMS--)
   {
    _delay_loop_2(250); // 延时1ms(粗略)
   }
 }
/*************************************************************************
* 名称: void PORT_Init(void)              
* 功能: 端口初始化                    
* 参数: 无                                   
* 返回: 无                                     
*************************************************************************/ 
void PORT_Init(void)
 {
  PORTB &=  ~((1 << PB1) | (1 << PB2));
  DDRB = (1 << PB1) | (1 << PB2); 
 } 
/*************************************************************************
* 名称: void Timer1_Init(void)              
* 功能: TIMER1初始化                    
* 参数: 无                                   
* 返回: 无                                     
*************************************************************************/
void Timer1_Init(void)
{
 //快速PWM模式频率3906.25Hz
 TCNT1 = 0x0000;
 OCR1A = 0x0000;
 TCCR1A = (1 << COM1A1) | (1 << COM1B1) | (1 << WGM10);
 //比较匹配清零TOP置位
 TCCR1B = (1 << WGM12) | (1 << CS10);
 //定时器1工作于8位快速PWM模式无分频

int main(void)
 {
  PORT_Init();
  Timer1_Init();
  while(1)
   {
    for(uchPWM = 0 ; uchPWM < 255; uchPWM++)
    {
     OCR1A = uchPWM;
     if(uchPWM == 0)
     {
      DelayMS(2000);
     }
     else
     {
      DelayMS(100);
     }     
    }
    for(uchPWM = 255 ; uchPWM > 0; uchPWM--)
    {
     OCR1A = uchPWM;
     if(uchPWM == 255)
     {
      DelayMS(2000);
     }
     else
     {
      DelayMS(100);
     }
     
    }
   }
 }

 

点击此处查看原文 >>

系统分类: 单片机   |    用户分类:    |    来源: 原创

评论(0) | 阅读(215)
发表于:2008-4-25 15:46:19
标签:RTC  STM32  学习笔记  

0

[原创]STM32学习笔记之—RTC

STM32学习笔记之—RTC

wormchenx@gmail.com

写这篇学习笔记的时候距上一篇笔记间隔的时间不短了,期间有网友关心询问为什么不更新文章,主要是这一段时间工作太忙了没有闲暇时间做下来学习,工作是重要的事情,不能把饭碗丢了啊o(_)o…,好了废话少说切入正题。

既然我们要使用RTC就要先对它有个大致的了解,知己知彼才能百战不殆嘛!STM32内部RTC功能非常实用,它的供电和时钟是独立于内核的,可以说是STM32内部独立的外设模块,有加上RTC内部寄存器不受系统复位掉电的影响,我们可以才用外部电池供电和32768表振晶体来实现真正RTC(实时时钟)功能。的这里引用手册里一段概述RTC由两个主要部分组成。第一部分(APB1接口)用来和 APB1总线相连。此单元还包含一组 16位寄存器,可通过 APB1总线对其进读写操作。APB1接口以 APB1总线时钟为时钟,用来与 APB1总线接口。

另一部分(RTC核)由一系可编程计数器组成,分成两个主要模块。第一个模块是 RTC的预分频模块,它可编程产生最长为 1秒的 RTC时间基准 TR_CLKRTC的预分频模块包含一个 20位的可编程分频器(RTC预分频器)。在每个TR_CLK周期中,如果在 RTC_CR 寄存器中设置相应允许位,则 RTC产生一个中断(秒中断)。第 2个模块是一个 32位的可编程的计数器,它可被初始化为当前的系统时间。系统时间以 TR_CLK增长并与存储在 RTC_ALR寄存器中的可编程的时间相比较,如果 RTC_CR控制寄存器中设置相应允许位,则比较匹配时将产生一个闹钟中断

对于第一次实用RTC的时候我们要对它进行配置一番,现在大致说一下(代码是通过调用RTC_Config函数来实现的):

1.      打开电源管理和备份寄存器时钟,提到备份寄存器这里要说一下,引用手册--备份寄存器是 10 16位的寄存器,可用来存储 20个字节的用户应用程序数据。他们处在备份域,当 VDD电源被断,他们仍然由 VBAT维持供电。当系统在待机模式下被唤醒,或系统复位或电源复位时,他们也会被复位”我们正式通过在备份寄存器写固定的数据来判断芯片是否第一次实用RTC,从而在系统运行RTC时提示配置时钟的。

2.      使能RTC和备份寄存器的访问(复位默认关闭)。引用手册--复位后,对备份寄存器和 RTC的访问被禁止,并且备份域被保护以防止可能存在的意外的写操作。电源控制寄存器(PWR_CR) DBP位必须被置 1,以允许访问备份寄存器和RTC.”因为程序要对RTC和备份寄存器操作,所以必须使能。

3.      选择外部低速晶体为RTC时钟,并使能时钟;

4.      使能秒中断,程序里在秒中断里置位标志位来通知主程序显示时间数据,同时在32位计数器到235959时清零;

5.      设置RTC预分频器值产生1秒信号计算公式 fTR_CLK = fRTCCLK/(PRL+1),我们设置32767来产生秒信号;

在这里要注意一下,所有在对RTC寄存器操作之前都要判断读写操作是否完成,也就是说当前是否有读写操作。系统内核是通过RTCAPB1接口来访问RTC内部寄存器的,所以在上电复位,休眠唤醒的时候,我们要先对RTC时钟与 RTC APB1时钟进重新同步,在同步完成后再对器进行操作,因为RTCAP1接口使用的系统APB1的时钟。上述配置在初次使用RTC时进行配置,在以后使用过程中,只要RTC外部电池持续供电,无论系统掉电还复位我们都无需重复配置,使用使能秒中断就可以了这一点很是方便嘿嘿...

在使用过程中我们通过读取32位可编程计数器的值来获取时钟信息,程序是通过串口2来向PC机发送数据来显示时钟的,并且还可以通过像STM32发送字符“S”来重新设置时钟数据,下面是几张调试的图片:

点击看大图

点击看大图

点击看大图

 

结束语:本也是才开始学习STM32,知道的也是皮毛而已,如果说的不对的地方还请指出。下面是工程代码,参考了官方的例子,硬件环境还是英培的EMSTM32V1,特介于篇幅这里就不做详细介绍了,代码有注释,不清楚的地方再联系我。

点击下载代码:rar

点击此处查看原文 >>

系统分类: 嵌入式   |    用户分类:    |    来源: 原创

评论(6) | 阅读(155)
发表于:2008-4-23 10:03:41
标签:L298  直流电机  

0

[原创]用L298驱动直流减速电机

   前一段有个朋友让我帮忙做一个电机控制的小东西要求是:控制直流减速的电机的启动、停止和正反转。起初我用4个N沟道IRF540N来做H桥驱动,发现H桥并不能输出12V电压给电机并且上桥避MOS很热,因为以前没有做过H桥后来查资料才知道是MOS管没有完全饱和导通再加上管子压降,所以输出电压不够。要想解决问题就必须提高上臂GS电压,电源是12V,栅极就必须是24V才能使上臂完全饱和导通。这样就必须提高电源,虽然有专用的桥驱动IC IRF2401但是一片几十元价格最后我还是放弃这种方案,选用小功率的直流电机驱动芯片L298,这是一款常用驱动IC,内部有两组H桥,驱动电流2A,40V正好满足我的要求(我的电机是直流12V15W),并且驱动电路简单。

   接下来我用ATTiny13来驱动L298来控制直流减速电机,程序到是很简单,但调试的时候又遇到了麻烦,搭好电路在运行的时候发现单片机有重启的现象,起初以为是电源功率不够电机启动拉低电源电压照成单片机重启,后来更换电源后问题依旧。既然不是电源问题,那就是有干扰信号影响单片机 ,我用示波器来监视单片机跟L298连接控制线并有杂波信号过来,这很让我感到很疑惑。一位同事看后我的电路说:“是不是管子电流不够啊?”我这才发现我的电源桥式整流用的是IN4007,电机消除反相电动势的是4个二极管是1N5819,这些管子电流都是1A,而我的电机电流是1.2A的,因为当时手头有这两种管子于是就随手焊上去了。在更换更大功率的管子1N5408和1N5822后,连续运行两天一切正常,问题的原因在于器件的参数不对。

   通过这次事情对于电机驱动我也总结了几点心得,以后再做这方面电路是值得注意的:

1.电机供电最好和单片机供电独立开来,中间加光耦隔离。防止电机通过回路干扰单片机。如果非要共用一个电源,那也要采取一些措施模拟地和数字地单点共地,采用0欧电阻或磁珠连接;

2.元件件的参数要留一定的富裕量,保证能可靠工作。IC器件VCC加104电容高频滤波;

3.PCB布线强弱电分开,尽量远离走线;

由于单片机程序比较简单就不在贴上来了,下面只放上原理图和实物图片:

点击看大图

点击看大图

点击看大图

点击此处查看原文 >>

系统分类: 单片机   |    用户分类:    |    来源: 原创

评论(10) | 阅读(290)
发表于:2008-4-5 22:54:32
标签:并口下载线  ISP  AVR  

0

[原创]AVR并口下载线自制

今天上午我用STK500下载程序的时候发现烧不能烧录程序了,读芯片数据也是时对时错,芯片ID号每读一次都不一样很是奇怪。再确定目标板硬件连接没有问题后,更换STK500晶体后故障依旧。这下我可着急了手头没有别的烧录器了,因为是给一个朋友做的一个小项目催的很急,再买去新的下载器一来一回也要耽误几天。后来想到了并口下载线,这个制作简单不需要单片机只需要很少几个元件就可以制作完成,上位机可以用双龙的SLISP,下午去中州商场买齐元件(很遗憾没有买到配套的壳体),晚上焊接完毕后接目标板测试下载程序正常,又抱着试试的心态重新烧写STK500的固件,我的STK500又奇迹般的好了,o(∩_∩)o...这个并口下载器可给我帮了大忙了,其实对于初学者是个不错的选择,整个下来也就7、8块钱,唯一缺点就是速度不是很快!

参考ouravr网站上的原理图:

点击看大图

我自己作的并口ISP正面图:

点击看大图

背面:

点击看大图

点击此处查看原文 >>

系统分类: 单片机   |    用户分类:    |    来源: 原创

评论(1) | 阅读(427)
发表于:2008-3-28 10:49:12
标签:ADC  DMA  USART  STM32  

2

[原创]STM32学习笔记之ADC

程序功能是把ADC1模块里通道14的输入电压转换后通过USART2发送到PC,在PC机上用串口调试助手观察接收数据:

STM32是12位ADC,测量结果基本还可以!程序用了DMA来传输ADC转换值,调高了读取速度。串口部分用是上一篇串口调试笔记里的代码。

/************************************************************************
     Copyright (c) 2008 wormchen            
     All rights reserved            
文 件 名: main.c             
说    明: 将ADC转换值通过串口发送到PC端         
主要硬件: EMSTM32V1+miniSTMV100(外部8MRC)        
编译环境: MDK3.10             
当前版本: 1.0              
作    者: 陈崇              
完成日期: 2008年3月24日9:08:41          
取代版本: 1.0              
原作  者: 陈崇             
完成日期: 2008年3月24日9:08:46         
************************************************************************/
#include <stm32f10x_lib.h>
#include <stdio.h>

#define ADC1_DR_Address    ((u32)0x4001244C)

#ifdef __GNUC__
  /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
     set to 'Yes') calls __io_putchar() */
  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */

vu16 ADC_ConvertedValue;

void RCC_Config(void);
void GPIO_Config(void);
void USART_Config(void);
void DMA_Config(void);
void ADC_Config(void);
void Put_String(u8 *p);
void Delay(vu32 nCount);
int main(void)
{
 RCC_Config();
 GPIO_Config();
 USART_Config();
 DMA_Config();
 ADC_Config();

 
 while(1)
 { 
 
  Delay(0x8FFFF);  
   printf("ADC = %X Volt = %d mv\r\n", ADC_ConvertedValue, ADC_ConvertedValue*3300/4096);
  
 }
}
/*************************************************
函数: void RCC_Config(void)
功能: 配置系统时钟
参数: 无
返回: 无
**************************************************/
void RCC_Config(void)
{
 ErrorStatus HSEStartUpStatus;//定义外部高速晶体启动状态枚举变量
 RCC_DeInit();//复位RCC外部设备寄存器到默认值
 RCC_HSEConfig(RCC_HSE_ON); //打开外部高速晶振
 HSEStartUpStatus = RCC_WaitForHSEStartUp();//等待外部高速时钟准备好
 if(HSEStartUpStatus == SUCCESS)//外部高速时钟已经准别好
    {

   RCC_HCLKConfig(RCC_SYSCLK_Div1);//配置AHB(HCLK)时钟=SYSCLK
   RCC_PCLK2Config(RCC_HCLK_Div1); //配置APB2(PCLK2)钟=AHB时钟
   RCC_PCLK1Config(RCC_HCLK_Div2);//配置APB1(PCLK1)钟=AHB 1/2时钟
      RCC_ADCCLKConfig(RCC_PCLK2_Div4);//配置ADC时钟=PCLK2 1/4
     
   RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
   //配置PLL时钟 == 外部高速晶体时钟*9
   RCC_ADCCLKConfig(RCC_PCLK2_Div4);//配置ADC时钟= PCLK2/4

      RCC_PLLCmd(ENABLE);//使能PLL时钟
   while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) //等待PLL时钟就绪
       {
       }
      RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);//配置系统时钟 = PLL时钟
  
      while(RCC_GetSYSCLKSource() != 0x08) //检查PLL时钟是否作为系统时钟
       {
       }
  }
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA, ENABLE);//使能DMA时钟
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);
  //使能ADC1,GPIOC时钟
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_AFIO, ENABLE);
  //打开GPIOD和AFIO时钟

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);//使能串口2时钟
}
/*************************************************
函数: void GPIO_Config(void)
功能: GPIO配置
参数: 无
返回: 无
**************************************************/
void GPIO_Config(void)
{
 //设置RTS(PD.04),Tx(PD.05)为推拉输出模式
 GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO初始化结构体
 GPIO_PinRemapConfig(GPIO_Remap_USART2, ENABLE);//使能GPIO端口映射USART2
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;//选择PIN4 PIN5
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //引脚频率50M
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//引脚设置推拉输出
 GPIO_Init(GPIOD, &GPIO_InitStructure);//初始化GPIOD
 //配置CTS (PD.03),USART2 Rx (PD.06)为浮点输入模式
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_6;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
 GPIO_Init(GPIOD, &GPIO_InitStructure);
 //配置PC4为模拟输入
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
 GPIO_Init(GPIOC, &GPIO_InitStructure);

}
/*************************************************
函数: void DMA_Config(void)
功能: DMA配置
参数: 无
返回: 无
**************************************************/
void DMA_Config(void)
{
 DMA_InitTypeDef DMA_InitStructure;//定义DMA初始化结构体
 DMA_DeInit(DMA_Channel1);//复位DMA通道1
 DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; //定义 DMA通道外设基地址=ADC1_DR_Address
 DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADC_ConvertedValue; //定义DMA通道存储器地址
 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//指定外设为源地址
 DMA_InitStructure.DMA_BufferSize = 1;//定义DMA缓冲区大小1
 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//当前外设寄存器地址不变
 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;//当前存储器地址不变
 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//定义外设数据宽度16位
 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //定义存储器数据宽度16位
 DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//DMA通道操作模式位环形缓冲模式
 DMA_InitStructure.DMA_Priority = DMA_Priority_High;//DMA通道优先级高
 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//禁止DMA通道存储器到存储器传输
 DMA_Init(DMA_Channel1, &DMA_InitStructure);//初始化DMA通道1
 DMA_Cmd(DMA_Channel1, ENABLE); //使能DMA通道1
}
/*************************************************
函数: void ADC_Config(void)
功能: ADC配置
参数: 无
返回: 无
**************************************************/
void ADC_Config(void)
{
  ADC_InitTypeDef ADC_InitStructure;//定义ADC初始化结构体变量
  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//ADC1和ADC2工作在独立模式
  ADC_InitStructure.ADC_ScanConvMode = ENABLE; //使能扫描
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//ADC转换工作在连续模式
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//有软件控制转换
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//转换数据右对齐
  ADC_InitStructure.ADC_NbrOfChannel = 1;//转换通道为通道1
  ADC_Init(ADC1, &ADC_InitStructure); //初始化ADC
  ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 1, ADC_SampleTime_28Cycles5);
  //ADC1选择信道14,音序器等级1,采样时间239.5个周期
  ADC_DMACmd(ADC1, ENABLE);//使能ADC1模块DMA
  ADC_Cmd(ADC1, ENABLE);//使能ADC1
  ADC_ResetCalibration(ADC1); //重置ADC1校准寄存器
  while(ADC_GetResetCalibrationStatus(ADC1));//等待ADC1校准重置完成
  ADC_StartCalibration(ADC1);//开始ADC1校准
  while(ADC_GetCalibrationStatus(ADC1));//等待ADC1校准完成
  ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能ADC1软件开始转换
}
/*************************************************
函数: void USART_Config(void)
功能: USART配置
参数: 无
返回: 无
**************************************************/
void USART_Config(void)
{
 USART_InitTypeDef USART_InitStructure; //定义串口初始化结构体
 USART_InitStructure.USART_BaudRate = 115200;//波特率9600
 USART_InitStructure.USART_WordLength = USART_WordLength_8b;//8位数据
 USART_InitStructure.USART_StopBits = USART_StopBits_1;//1个停止位
 USART_InitStructure.USART_Parity = USART_Parity_No ; //无校验位
 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
 //禁用RTSCTS硬件流控制
 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//使能发送接收
 USART_InitStructure.USART_Clock = USART_Clock_Disable; //串口时钟禁止
 USART_InitStructure.USART_CPOL = USART_CPOL_Low; //时钟下降沿有效
 USART_InitStructure.USART_CPHA = USART_CPHA_2Edge;//数据在第二个时钟沿捕捉
 USART_InitStructure.USART_LastBit = USART_LastBit_Disable;
 //最后数据位的时钟脉冲不输出到SCLK引脚
 USART_Init(USART2, &USART_InitStructure);//初始化串口2
 USART_Cmd(USART2, ENABLE);//串口2使能
}
/*************************************************
函数: void Put_String(void)
功能: 向串口输出字符串
参数: 无
返回: 无
**************************************************/
void Put_String(u8 *p)
{
 while(*p)
 {
  USART_SendData(USART2, *p++);
  while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET)
  {
   
  }
 }
}
/*****************************************************
函数: void Delay(vu32 nCount)
功能: 延时指定时间
参数: vu32 nCount 延时指定时间
返回: 无
******************************************************/
void Delay(vu32 nCount)
{
  for(; nCount != 0; nCount--);
}
/*****************************************************
函数:PUTCHAR_PROTOTYPE
功能: 重定向C库printf函数
参数: 无
返回: 无
*****************************************************/
PUTCHAR_PROTOTYPE
{
 USART_SendData(USART2, (u8) ch);//发送一字节数据
 while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET)
 {
 }//等待发送完成
 return ch;
}

点击此处查看原文 >>

系统分类: 嵌入式   |    用户分类:    |    来源: 原创

评论(3) | 阅读(575)
发表于:2008-3-25 16:22:18
标签:重映射  STM32  

0

[原创]STM32学习笔记之 重映射功能

最近在学习STM32,在BZ上一篇关于的串口通信文章里有这么一段代码:RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_AFIO,ENABLE);

当初是参考开发的里子写的一直对GPIOD或上“RCC_APB2Periph_AFIO”这句话的意思没搞懂,通过这几天在网上查找资料和看手册,终于高清楚了,不敢独享,希望能对跟我一样的新手有所帮助吧o(∩_∩)o...

STM32上有很多I/O口,也有很多的内置外设想I2C,ADC,ISP,USART等 ,为了节省引出管脚,这些内置外设基本上是与I/O口共用管脚的,也就是I/O管脚的复用功能。但是STM32还有一特别之处就是:很多复用内置的外设的I/O引脚可以通过重映射功能,从不同的I/O管脚引出,即复用功能的引脚是可通过程序改变的。知道了这些我们就不难理解上面代码的意思了,程序中用到的USART2外设的TX,RX分别对应PA2,PA3,但是我的学习板上的PA2,PA3引脚接了其他设备,但是为了还要用USART2,“RCC_APB2Periph_GPIOD |RCC_APB2Periph_AFIO”就打开了GPIOD重映射功能把USART2设备的TX,RX映射到PD5,PD6上,我们在这两个引脚上接上MAX232串口芯片就可以使用USART2串口通信了。那为看官该问:“USART2是不是可以映射到任意管脚呢?”答案是否定的,它只能映射到固定的管脚,下图是USART2重映射表

点击看大图

其他外设的重映射可以参考STM32100X手册。

为了节省IO资源单片机会在一个IO上复用很多功能,一般的单片机用到 一个功能后就能再用两外复用的功能了,这就体现出了STM32 GPIO的强大功能了,我们用重映射的方法把其中一个外设映射到其他IO脚上,这样就可以充分利用片内资源!

点击此处查看原文 >>

系统分类: ARM   |    用户分类:    |    来源: 原创

评论(5) | 阅读(306)
发表于:2008-3-24 9:44:42
标签:STM32  串口  

1

[原创]STM32学习笔记之 串口通讯

参考开发板例子写的串口通讯的小程序。主要功能是把PC机发送的数据接收后再返回给PC机参数9600,8,1,N。

/************************************************************************
     Copyright (c) 2008 wormchen             
     All rights reserved            
文 件 名: main.c             
说    明: 串口发送接收数据 将PC端发来的数据返回给PC         
主要硬件: EMSTM32V1+miniSTMV100(外部8MRC)        
编译环境: MDK3.10             
当前版本: 1.0              
作    者: 陈崇              
完成日期: 2008年3月24日9:08:41          
取代版本: 1.0              
原作  者: 陈崇             
完成日期: 2008年3月24日9:08:46         
************************************************************************/
#include

 

void RCC_Config(void);
void GPIO_Config(void);
void USART_Config(void);
void Put_String(u8 *p);

int main(void)
{
 RCC_Config();
 GPIO_Config();
 USART_Config();
 Put_String("\r\n请发送数据_\r\n");
 while(1)
 { 
  while(1)  
  {
   if(USART_GetFlagStatus(USART2, USART_FLAG_RXNE) == SET)
   {
     
      USART_SendData(USART2, USART_ReceiveData(USART2));
   }
  }   
 }
}
/*************************************************
函数: void RCC_Config(void)
功能: 配置系统时钟
参数: 无
返回: 无
**************************************************/
void RCC_Config(void)
{
 ErrorStatus HSEStartUpStatus;//定义外部高速晶体启动状态枚举变量
 RCC_DeInit();//复位RCC外部设备寄存器到默认值
 RCC_HSEConfig(RCC_HSE_ON); //打开外部高速晶振
 HSEStartUpStatus = RCC_WaitForHSEStartUp();//等待外部高速时钟准备好
 if(HSEStartUpStatus == SUCCESS)//外部高速时钟已经准别好
    {

   RCC_HCLKConfig(RCC_SYSCLK_Div1);//配置AHB(HCLK)时钟等于==SYSCLK
   RCC_PCLK2Config(RCC_HCLK_Div1); //配置APB2(PCLK2)钟==AHB时钟
   RCC_PCLK1Config(RCC_HCLK_Div2);//配置APB1(PCLK1)钟==AHB1/2时钟
    
     
   RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
   //配置PLL时钟 == 外部高速晶体时钟*9

      RCC_PLLCmd(ENABLE);//使能PLL时钟
   while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) //等待PLL时钟就绪
       {
       }
      RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);//配置系统时钟 = PLL时钟
  
      while(RCC_GetSYSCLKSource() != 0x08) //检查PLL时钟是否作为系统时钟
       {
       }
  }
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_AFIO, ENABLE);
  //打开GPIOD和AFIO时钟
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);//使能串口2时钟
}
/*************************************************
函数: void GPIO_Config(void)
功能: GPIO配置
参数: 无
返回: 无
**************************************************/
void GPIO_Config(void)
{
 //设置RTS(PD.04),Tx(PD.05)为推拉输出模式
 GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO初始化结构体
 GPIO_PinRemapConfig(GPIO_Remap_USART2, ENABLE);//使能GPIO端口映射USART2
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;//选择PIN4 PIN5
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //引脚频率50M
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//引脚设置推拉输出
 GPIO_Init(GPIOD, &GPIO_InitStructure);//初始化GPIOD

 //配置CTS (PD.03),USART2 Rx (PD.06)为浮点输入模式
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_6;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
 GPIO_Init(GPIOD, &GPIO_InitStructure);
}
/*************************************************
函数: void USART_Config(void)
功能: USART配置
参数: 无
返回: 无
**************************************************/
void USART_Config(void)
{
 USART_InitTypeDef USART_InitStructure; //定义串口初始化结构体
 USART_InitStructure.USART_BaudRate = 9600;//波特率9600
 USART_InitStructure.USART_WordLength = USART_WordLength_8b;//8位数据
 USART_InitStructure.USART_StopBits = USART_StopBits_1;//1个停止位
 USART_InitStructure.USART_Parity = USART_Parity_No ; //无校验位
 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
 //禁用RTSCTS硬件流控制
 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//使能发送接收
 USART_InitStructure.USART_Clock = USART_Clock_Disable; //串口时钟禁止
 USART_InitStructure.USART_CPOL = USART_CPOL_Low; //时钟下降沿有效
 USART_InitStructure.USART_CPHA = USART_CPHA_2Edge;//数据在第二个时钟沿捕捉
 USART_InitStructure.USART_LastBit = USART_LastBit_Disable;
 //最后数据位的时钟脉冲不输出到SCLK引脚
 USART_Init(USART2, &USART_InitStructure);//初始化串口2
 USART_Cmd(USART2, ENABLE);//串口2使能
}
/*************************************************
函数: void Put_String(void)
功能: 向串口输出字符串
参数: 无
返回: 无
**************************************************/
void Put_String(u8 *p)
{
 while(*p)
 {
  USART_SendData(USART2, *p++);
  while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET)
  {
   
  }
 }
}

点击此处查看原文 >>

系统分类: ARM   |    用户分类:    |    来源: 原创

评论(3) | 阅读(401)
发表于:2008-3-19 16:48:19
标签:STM32  入门  

0

[原创]STM32学习笔记之入门 发帖庆贺LED流水灯

用的是英培特的EMSTM32V1学习板,按下按键后开是流水灯显示,很简单不过以前没接触过ARM还是费了好大劲!

/************************************************************************
     Copyright (c) 2008 wormchen             
     All rights reserved             
文 件 名: main.c              
说    明: 流水灯 按下Key键开始LED1 -LED4流水显示          
主要硬件: EMSTM32V1+miniSTMV100(内部8MRC)        
编译环境: MDK3.10              
当前版本: 1.0               
作    者: 陈崇               
完成日期: 2008年3月19日16:05:39           
取代版本: 1.0               
原作  者: 陈崇              
完成日期: 2008年3月19日16:05:44          
************************************************************************/ 
 
#include

GPIO_InitTypeDef GPIO_InitStructure; //GPIO初始化结构体

/*****************************************************
函数: void Delay(vu32 nCount)
参数: vu32 nCount 延时时间
描述: 延时指定时间
返回: 无
******************************************************/
void Delay(vu32 nCount)
{
  for(; nCount != 0; nCount--);
}
int main(void)
{
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);//使能GPIOC时钟
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
 //选择引脚6,7,8,9
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //带上拉输出
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //输出频率最大50M
 GPIO_Init(GPIOC, &GPIO_InitStructure); //初始化PC6,7,8,9引脚
  
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//使能GPIOB时钟  
 GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_9; //选择引脚9
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮点输入
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //输入频率最大50M
 GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PB9引脚

 while(1)
  {
   if(!GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_9))//如果按下Key开始流水
    {
     while(1)
     {
      GPIO_SetBits(GPIOC, GPIO_Pin_6);//点亮LED1
      Delay(0x1ffff); //延时
      GPIO_ResetBits(GPIOC, GPIO_Pin_6);//关闭LED1
  
      GPIO_SetBits(GPIOC, GPIO_Pin_7);//点亮LED2
      Delay(0x1ffff); //延时
      GPIO_ResetBits(GPIOC, GPIO_Pin_7);//关闭LED2

      GPIO_SetBits(GPIOC, GPIO_Pin_8);//点亮LED3
      Delay(0x1ffff); //延时
      GPIO_ResetBits(GPIOC, GPIO_Pin_8);//关闭LED3

      GPIO_SetBits(GPIOC, GPIO_Pin_9);//点亮LED4
      Delay(0x1ffff); //延时
      GPIO_ResetBits(GPIOC, GPIO_Pin_9);//关闭LED4

      GPIO_SetBits(GPIOC, GPIO_Pin_8);//点亮LED3
      Delay(0x1ffff); //延时
      GPIO_ResetBits(GPIOC, GPIO_Pin_8);//关闭LED3
      
      GPIO_SetBits(GPIOC, GPIO_Pin_7);//点亮LED2
      Delay(0x1ffff); //延时
      GPIO_ResetBits(GPIOC, GPIO_Pin_7);//关闭LED2

     }
   
    }
  }

}

工程项目rar

点击此处查看原文 >>

系统分类: ARM   |    用户分类:    |    来源: 原创

评论(1) | 阅读(309)
发表于:2008-3-14 10:18:43
标签:学习板  M48  AVR  

0

[原创]我自己的m48学习板

以前学习AVR的时候都是焊接万能板,由于板子不太好焊几次就废了很是麻烦,最后终于决定自己作一块学习板方便自己平时使用。前天拿到板子,昨天花一上午的时间焊好,由于焊接贴片功夫不到家板子焊的很难看,后来用无水乙醇清洗后还能拿的出手!下午简单测试了一下串口和ISP目前还没什么大问题,:-)

点击看大图

点击看大图

点击看大图

点击看大图

点击看大图

点击此处查看原文 >>

系统分类: 单片机   |    用户分类:    |    来源: 原创

评论(3) | 阅读(334)
发表于:2008-1-14 14:20:55
标签:电机  调速  51  

2

[原创]电机调速

利用上一篇的过零检测电路,过零信号接51单片机外部中断1(下降沿触发),单片机延时触发可控硅导通实现调速。

点击看大图

点击看大图

*感谢郭隆红网友帮我找出错误

点击看大图

部分程序:

/*********************************************************************
函数名称: void ISR_Int1OverZeroDetect() interrupt IE1_VECTOR             
函数功能: 外部中断1过零信号捕获中断服务程序                
入口参数:                      
返回  值:                                
*********************************************************************/
 void ISR_Int1OverZeroDetect() interrupt IE1_VECTOR
{   
  switch(g_uchWindSpeed)//设置定时器延时
 {
  case 0:
  {
   TH1 = (65536 - 1800) / 256;                         
      TL1 = (65536 - 1800) % 256;     
   break;
  }
  case 1:
  {
   TH1 = (65536 - 6000) / 256;                         
      TL1 = (65536 - 6000) % 256; 
   break;
  }
  case 2:
  {
   TH1 = (65536 - 7000) / 256;                         
      TL1 = (65536 - 7000) % 256; 
   break;
  }
  }
 TR1 = 1; // 启动定时器1

/*********************************************************************
函数名称: void ISR_Timer1TriacsTrigger() interrupt TF1_VECTOR            
函数功能: 定时器0触发可控硅中断服务程序               
入口参数:                       
返回  值:                                
*********************************************************************/
void ISR_Timer1TriacsTrigger() interrupt TF1_VECTOR
{
  TH1 = 0xFF; //定时器0延时200                        
    TL1 = 0x38;
 if(g_bTirggerFlag)
    {
  P2_5 = 1;
        g_bTirggerFlag = 0;
        TR1 = 0; // 关闭定时器0
    }
    else
    {
  P2_5 = 0;
        g_bTirggerFlag = 1;
    }
}

/*********************************************************************
函数名称: void Init_System(void)               
函数功能: 系统初始化                  
入口参数:                      
返回  值:                                
*********************************************************************/ 
void System_Init(void)
{  
 TMOD = 0x11; //定时器0,1工作模式1, 16位定时方式

 ET1 = 1; //使能定时器1溢出中断
 EX0 = 1;
 IT0 = 1;
 EX1 = 0; //外部中断1禁止
 IT1 = 1; //外部中断1下降沿触发中断
  EA = 1; //全局中断使能
}

点击此处查看原文 >>

系统分类: 单片机   |    用户分类:    |    来源: 原创

评论(3) | 阅读(1101)
总共 , 当前 /,234下一页