/********************************************************************** * 作者:杨志强 EWOODPECKER_CHRIS YANG * 日期:2017.03.04 * 特点: STM8S003F3P6 测试串口; * 时钟:内部 16MHz; 38KHz => 26.31 us; (高电平 13.2) ***********************************************************************/ // 头文件 宏定义 #include <iostm8s003f3.h> #include"stdio.h" // 声明;常用数据类型定义*************************/ #define u8 uint8_t #define u16 uint16_t #define u32 uint32_t typedef unsigned char uint8_t; typedef unsigned int uint16_t; typedef unsigned long uint32_t; // 位定义, 控制信号口; #define KEY PD_IDR_IDR1 // 按键 KEY 指定到 PA1 ; 输入寄存器; (上拉输入 ) 内部高电平,被动拉低; #define LED PA_ODR_ODR3 // 指示灯 LED //#define IR PD_ODR_ODR3 // IR红外遥控 发射; #define IR PD_ODR_ODR2 // IR红外遥控 发射; // 数组定义; unsigned char Table[8]; // 存储 Music 命令码 // 变量定义; u8 wy[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; // 0000 0001 / 0000 0010 / 0000 0100 / 0000 10000 u16 end_count = 0; u8 count = 0; u8 count0 = 0; u8 user; //u16 system = 0x00ff; u16 system = 0x00; u16 time_cnt = 0; u8 hc; /********************************************************************** * 函数: CLK_Init(void) * 功能: 时钟设置;配置成 16MHz; * 输入: 无; * 输出: 无; ***********************************************************************/ void CLK_Init(void) { CLK_CKDIVR = 0x00; // 配置成 16MHz; } /********************************************************************** * 函数: eeprom_write(u8 addr, u8 dat) * 功能: EEPROM指定地址写入一个数据 * 输入: 无; * 输出: 无 ***********************************************************************/ void eeprom_write(u8 addr, u8 dat) { u8 *p; p = (u8 *)(0x4000+addr); *p = dat; while(!(FLASH_IAPSR & 0x04)); //等待写操作成功 } /********************************************************************** * 函数: TIM1_Init(unsigned int psc,unsigned int arr) //psc 分频系数 arr 计数值 * 功能: 时钟定义 初始化; * 输入: 无 * 输出: 无 ***********************************************************************/ void Init_TIM1(u16 psc,u16 arr) //psc 分频系数 arr 计数值 { //1. 配置定时器 工作模式 和系统时钟; TIM1_CR1 = 0x00; /* ARPE_7 = 0; // ( ) CMS_6 = 0; // ( ) CMS_5 = 0; // ( ) DIR_4 = 0; // ( 0:计数器向上计数; 1:计数器向下计数?) OPM_3 = 0; // ( 0:发生更新事件时,计数器不停止;1: 发生下一次更新事件时(清除 CEN 位,计数器停止; ) URS_2 = 0; // ( ) UDIS_1 = 0; // ( ) CEN_0 = 0; // ( 0: 禁止计数; 关闭计数器, 使用时,再开启;) */ //2. 配置定时器 中断; TIM1_IER = 0x01; // 0000 0001(中断使能寄存器 )允许更行中断 /* UIE_0 = 1; // (0: 禁止更新中断; 1: 允许更新中断;) */ //3. 进行时钟分频; TIM1_PSCRH = (psc-1)/256; //进行分频值 TIM1_PSCRL = (psc-1)%256; //4. 设定计数值上限; TIM1_ARRH = arr/256; // 溢出值 高位; TIM1_ARRL = arr%256; // 溢出值 低位; //5. 开始计数; //TIM1_CR1 |=0x01; //开始计数 } /********************************************************************** * 函数: TIM1 中断函数; * 功能: 时钟计时 中断标志位 清 0 ; * 输入: 无; * 输出: 无 打开 时钟 计时,让他一直不停 的 计数; 计数,根据不同 阶段 来设定 不同的参数,以示 区分; ***********************************************************************/ #pragma vector=13 __interrupt void Inter_Timer1_Over(void) { //TIM1_SR1 = 0x00; // 中断标志位 清 0 TIM1_SR1_UIF = 0; // 无更新事件 产生; TIM1_CR1_CEN = 0; // 停止记数; } // D 端口 外部 中断函数; /********************************* 1120us = 0; 2250us = 1; 13500us = start; < 1050 X 在 1700 为分界点; 1050 < 1120 < 1700 < 2250 #pragma vector = 8 __interrupt void Inter_EXTI3_IR_Handle(void) { uchar IR_Time_H; uchar IR_Time_L; uint IR_Time; // 记录脉冲的周期长度; //读数据之前先停止计数器 TIM2_CR1_CEN=0; //读计数器的值 TIMx_CNTRH/TIMx_CNTRL IR_Time_H=TIM2_CNTRH; IR_Time_L=TIM2_CNTRL; //数据转换 每计 1 次数 用时 1us; IR_Time=IR_Time_H*256+IR_Time_L; //清零计数器,以计算两次进入中断的时间 TIM2_CNTRH=0; TIM2_CNTRL=0; //启动计数器 TIM2_CR1_CEN=1; //如果时间间隔大于11ms,说明接收到启动码 (引导码 9000us 高电平) if(IR_Time>11000) { IR_Start=1; // 启动标志置一 IR_Num=0; // 清零IR_Num,保证数据的准确性,该语句可以保证不会因为接收到部分数据而 } // 导致数据不准确,原理是启动后必须接收到全部数据,数据才有效 //数据时间间隔大余1.05ms,故不在这个范围则说明不是数据,则返回 if(IR_Time<1050) { return; // 退出操作,不再往下执行语句; } //如果已经收到启动代码,且数据在有效范围内 if((IR_Start==1) && (IR_Time<2600)) { //因为先发地址高位,所以要向右移动 IR_data<<=1; // 0000 0100 -> 0000 1000 -> 0001 0000 注意:左移,补 0 ; //如果数据间隔大于数据0和数据1中间数值,则认为收到数据1 if(IR_Time>1700) { IR_data|=1; // 例:0000 1000 | 0000 0001 -> 0000 1001 让最低位 置 1; } //收到一位后IR_Num加1 IR_Num++; //如果IR_Num>31,即等于32,33,34....(为保证可靠,用大于)时,说明数据已经收完 if(IR_Num>31) { //数据收完后接收结束标志置位 Sign_Data_Ok=1; //启动标志清零 IR_Start=0; //收到全部数据后关闭定时器,可节能,也避免出错 TIM2_CR1_CEN=0; } } IR_Data();// 对数据进行转换; } *********************************/ // 初始化:TIME2; void Init_TIME2(void) { // 自动分频器 TIMx_PSCR //TIM2_PSCR_PSC=1; //0000 0001: 1MHz,计数器为1时定时时间约1us (默认上电时,16MHz,8分频; 再 2 预分频成 1MHz; TIM2_PSCR_PSC=4; // 主时钟 16MHz, TIM2 采用 16 分频 = 1MHZ(1us); //自动重装为10000保证正常接收过程中不会溢出 TIM2_ARRH=0xff; TIM2_ARRL=0xff; // ARRH/ARRL: 当自动装载的值为 0 时,计数器不工作; TIM2_EGR_UG=1; //重新初始化寄存器 // UG 产生更新事件 0:无动作; 1 重新初始化计数器,并产生一个更新事件 // 注意,预分频器的计数器也被清 0; } /********************************************************************** * 函数: TIM2 初始化 * 功能: * 输入: * 输出: 16位 向上计数 和 自动装载计数器; 4位可编程;分频系数:1-32768 之间的 2 的幂; 分频,向上计数,自动重装载 ***********************************************************************/ void Init_TIME2_2(void) { TIM2_ARRH = (u8)(1000 >> 8); TIM2_ARRL = (u8)(1000); TIM2_PSCR = 0x04; // 16M/(2^4) = 1M TIM2_EGR = 0x01; // 产生更新事件 TIM2_SR1 = (~0x01); // 清除更新中断标志; TIM2_CR1 |= 0x01; // 使能 计数器 TIM2_IER |= 0x01; // 更新中断使能; } #pragma vector = 15 __interrupt void Inter_Timer2_Over(void) { //TIM1_SR1 = 0x00; // 中断标志位 清 0 TIM2_SR1 = (~0x01); // 清除无更新 中断 标志; time_cnt++; if(time_cnt > 999) { time_cnt = 0; LED = !LED; } // TIM1_CR1_CEN = 0; // 停止记数; } /********************************************************************** * 函数: Uart1_Init(void) * 功能: Uart1 串口初始化环境设置; * 输入: 无; * 输出: 无 ***********************************************************************/ void Init_UART1(void) { UART1_CR1 = 0x00; // 0000 0000 (5:使能)(4: 1个起始位,8个数据位);一位起始位,八位数据,不校验 //UART1_CR2 = 0x2c; // 0010 1100 (开打接收中断,发送中断可以不设置,发送是我们主动发送的)(开启 发送使能,接收使能)()允许接收中断 发送接收使能 //UART1_CR2 = 0x08; // 0000 1000 发送使能 1开启;不要发送中断 ,不要接收中断; UART1_CR3 = 0x00; // 0000 0000 一位停止位 // UART1_BRR2 = 0x0b; // 波特率 115200@ 16Mhz // BRR2 要先写于 BRR1; // UART1_BRR1 = 0x08; UART1_BRR2 = 0x03; // 波特率 9600 @ 16Mhz(16 000 000 /9600) = 1667; UART1_BRR1 = 0x68; // 1667 的 16进制:(1667 = 0x0683 ) UART_DIV = 0x0683; UART1_BRR2 =0X03; UART1_BRR1 = 0X68; //4.使能发送和接收功能 UART1_CR2 = 0x2C; // 0010 1100 开启: ( 发送 + 接收 使能 ) +( 接收 中断) //UART1_CR2 = 0x0C; // 0000 1100 开启: ( 发送 + 接收 使能 ) /* 7-TIEN 发送 中断使能; 6-TCIEN 发送 完成 中断 使能; 4-ILIEN IDLE 中断 使能; 2-REN 接收使能; 3-TEN 发送使能; 5-RIEN 接收 中断使能; */ //UART1_CR2 = 0x08; // 0000 1000 开启: 发送使能; 关闭:接收使能; 不要发送中断 ,不要接收中断?} } /********************************************************************** * 函数: eeprom_read( u8 addr){ * 功能: EEPROM 指定地址读出一个数据 * 输入: 无; * 输出: 有 ***********************************************************************/ u16 eeprom_read( u8 addr) { u8 *p; p=( u8 *)(0x4000+addr); return *p; } /********************************************************************** * 函数: Delay_Nms(u16 x) * 功能: 延时Nms; * 输入: int x; * 输出: 无 ***********************************************************************/ void Delay_Nms(u16 x) { u16 a,b; while(x--) { for(a=0; a<18; a++) { for(b=0; b<176; b++); // 175->998us; 176->1.00425ms; } } } /********************************************************************** * 函数: Delay_1ms(int i) * 功能: 1ms 延时 * 输入: 无 * 输出: 无 ***********************************************************************/ void Delay_50us(u16 i) { u8 j; while(i--) { for(j=0; j<154; j++) //50us基准延时程序 { ; } } } /********************************************************************** * 函数: Delay_1ms(int i) * 功能: 38 KHz * 输入: 无 * 输出: 无 ***********************************************************************/ void Delay_13us_duli(u16 i) { while(i--) { for(u8 j=0; j<30; j++) //38KHz 基准延时程序 高电平 13us.= 26us; { ; } } } /********************************************************************** * 函数: Delay_1ms(int i) * 功能: 38 KHz * 输入: 无 * 输出: 无 35 -> (37.7-38 KHz); ***********************************************************************/ void Delay_13us(u16 i) { while(i--) { for(u8 j=0; j<35; j++) //38KHz 基准延时程序 高电平 13us.= 26us; { ; } } } //发射 38KHz 的程序; 1000 000 us / 38 000 Hz = 26.315789 us void khz_38() { IR = 1; // LED = 1; Delay_13us(1); IR = 0; // LED = 0; Delay_13us(1); // khz(116); // 3.028 ms // khz(64); // 2.006 ms // khz(40); // 1.052 ms // delayms(125); // 2.012 ms // delayms(65); // 1.054 ms // delayms(93); // 1.5 ms } /********************************************************************** * 函数: Delay100us(void) * 功能: 100us 延时 精准; 误差 0us * 输入: 无; * 输出: 无 ***********************************************************************/ void Delay_100us(void) { Delay_50us(2); } /********************************************************************** * 函数: LED_Flash() * 功能: 指示灯 * 输入: 无 * 输出: 无 ***********************************************************************/ void LED_Flash(u8 x) { u8 i; for (i = 0; i<= x; i++) { LED = 0; Delay_Nms(3); LED = 1; Delay_Nms(3); } LED = 1; } /********************************************************************** * 函数: GPIO_Init_Time() * 功能: IO 端口初始化配置; * 输入: 无; * 输出: 无 ***********************************************************************/ void GPIO_Init() { PA_DDR |= 0x08; // 0000 1000; 1:输出;0:输入 ( PA1_KEY 按键 上拉输入;) PA_CR1 |= 0x08; // 0000 1000; 1:推挽;0:开漏; PA_CR2 = 0x00; // 0000 0000; PB_DDR |= 0x10; // 0001 0000; 1:输出;0:输入 (PB4_LED指示灯 推挽输出 110) PB_CR1 |= 0x30; // 0011 0000; 1:推挽;0:开漏; PB_CR2 = 0x00; // 0000 0000; PC_DDR |= 0xF0; // 0000 0000; 1:输出;0:输入 PA1 按键上拉输入; PC_CR1 |= 0xF0; // 1111 0000; 1:推挽;0:开漏; PC_CR2 = 0x00; // 0000 0100 PD_DDR |= 0x0C; // 0000 1100; 1:输出;0:输入 ( PA1_KEY 按键 上拉输入;) PD_CR1 |= 0x0E; // 0000 1110; 1:推挽;0:开漏; PD_CR2 = 0x00; // 0000 0000; // 端口初始化设置;----------------------------------------------------------------------------- PA_ODR |= 0xFF; // 0x3F: 1111 1111; |= 将 PA端口全部置 1 (高电平 ) PB_ODR |= 0xFF; PC_ODR |= 0xFF; PD_ODR |= 0xFF; } void send_1(void) { ///////////////////////////////////////////////////// u8 end_count = 3; //发送 公共的 0.56ms 高电平 IR = 1; u8 count = 0; u8 count0 = 0; do { IR = 1; Delay_13us(1); IR = 0; Delay_13us(1); count++; if(count >= 8) { count = 0; count0 ++; } } while(count0 < end_count); ///////////////////////////////////////////////////// end_count = 7; //发送 底电平 0.56ms 1.125 ms IR = 0; count0 = 0; count0 = 0; do { count++; if(count >= 100) { count = 0; count0 ++; } } while(count0 < end_count); } // send_1(); // 数据 0; 1.125 // send_0(); // 数据 0; 2.25 void send_0(void) { ///////////////////////////////////////////////////// u8 end_count = 3; //发送 公共的 0.56ms 高电平 IR = 1; u8 count = 0; u8 count0 = 0; do { IR = 1; Delay_13us(1); IR = 0; Delay_13us(1); count++; if(count >= 7) { count = 0; count0 ++; } } while(count0 < end_count); ///////////////////////////////////////////////////// end_count = 21; //发送 底电平 0.56ms 1.125 ms IR = 0; count0 = 0; count0 = 0; do { count++; if(count >= 100) { count = 0; count0 ++; } } while(count0 < end_count); } void send(u8 dat) { u8 s = 0, user = 0, shu_ju = 0, hc = 0; u8 count0 = 0; /**********发送引导码**********************/ end_count = 8; // 发送 9ms 起始码的高电平 IR = 1; count = 0;; do { IR = 1; Delay_13us(1); IR = 0; Delay_13us(1); count++; if(count >= 42) { count = 0; count0 ++; } } while(count0 < end_count); end_count = 53; // 发送 4.5ms 结束码的低电平 IR = 0; count0 = 0; do { count++; if(count >= 100) { count = 0; count0 ++; } } while(count0 < end_count); /**********发送 系统 码***********************/ user = system; for(u8 s = 0; s < 8; s++) { hc = user & wy[s]; // 发送 脉冲 间距 if(hc == 0) { send_1(); // 数据; 2.25 } else { send_0(); // 数据; 1.125 } } /********** 发送 系统 反码 ***********************/ for(u8 s = 0; s < 8; s++) { hc = user & wy[s]; //发送脉冲间距 if(hc == 0) { send_0(); // 数据; 1.125 } else { send_1(); // 数据; 2.25 } } /**********发送 客户 码 ***********************/ user = 0x0C; for(u8 s = 0; s < 8; s++) { hc = user & wy[s]; // 发送 脉冲 间距 if(hc == 0) { send_1(); // 数据; 2.25 } else { send_0(); // 数据; 1.125 } } /**********发送 客户 反码 ***********************/ for(u8 s = 0; s < 8; s++) { hc = user & wy[s]; // 发送 脉冲 间距 if(hc == 0) { send_0(); // 数据; 1.125 } else { send_1(); // 数据; 2.25 } } send_1(); // 数据; 2.25 } /********************************************************************** * 函数: main() * 功能: 主函数; * 输入: 无; * 输出: 无 ***********************************************************************/ void main() { asm("sim"); // disable all interrupt EA=0; // 关闭 中断; CLK_Init(); // 时钟初始化| 没有打开时钟计时,在需要时,才开启; // TIM1_Init(16000,1000); // 定时器初始化| f=16M/16000=1kHz time=1ms*1000=1s GPIO_Init(); // asm("rim"); //enable all interrupt EA=1; // 打开 中断; // TIM1_CR1 |= 0x01; //开始计数 while(1) { // IR = 1; //// LED = 1; // Delay_13us(1); // IR = 0; //// LED = 0; // Delay_13us(1); // khz_38(); if(!KEY) { Delay_Nms(10); if(!KEY) { LED_Flash(1); send(0xFF); // 发送 红外 编码; } } } }
联系人:客服在线
手机:全工:13903011251
电话:李R:13530006400
邮箱:729986191@qq.com
地址: GUANGDONG PROVINCE