sys.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. //#include <stm32f10x_lib.h>
  2. #include "sys.h"
  3. //////////////////////////////////////////////////////////////////////////////////
  4. //V1.4修改说明
  5. //把NVIC KO了,没有使用任何库文件!
  6. //加入了JTAG_Set函数
  7. //////////////////////////////////////////////////////////////////////////////////
  8. #ifdef CHANGE_IAR_SYS_C
  9. #define IPR IP
  10. #endif
  11. //函数说明:十六进制转字符串函数 (8bit)
  12. //参数:hex_str:要转换的十六进制数组
  13. // char_str:转换后存放的字符数组
  14. // tran_num:转换的个数
  15. //返回值:无
  16. void Hex_Tran_Char_8bit ( u8* hex_str, u8* char_str, u8 tran_num )
  17. {
  18. u8 i, model[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
  19. for ( i = 0; i < tran_num; i++ )
  20. {
  21. char_str[2 * i] = model[ ( hex_str[i] >> 4 ) & 0x0F];
  22. char_str[2 * i + 1] = model[hex_str[i] & 0x0F];
  23. }
  24. char_str[2 * i] = 0; //字符串结束符
  25. }
  26. //函数说明:十六进制转字符串函数(16bit)
  27. //参数:hex_str:要转换的十六进制数组
  28. // char_str:转换后存放的字符数组
  29. // tran_num:转换的个数
  30. //返回值:无
  31. void Hex_Tran_Char_16bit ( u16* hex_str, u8* char_str, u8 tran_num )
  32. {
  33. u8 i, model[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
  34. for ( i = 0; i < tran_num; i++ )
  35. {
  36. char_str[4 * i] = model[ ( hex_str[i] >> 12 ) & 0x0F];
  37. char_str[4 * i + 1] = model[ ( hex_str[i] >> 8 ) & 0x0F];
  38. char_str[4 * i + 2] = model[ ( hex_str[i] >> 4 ) & 0x0F];
  39. char_str[4 * i + 3] = model[hex_str[i] & 0x0F];
  40. }
  41. char_str[4 * i] = 0; //字符串结束符
  42. }
  43. //函数说明:设置向量表偏移地址
  44. //参数:NVIC_VectTab - 基址
  45. // Offset - 偏移量
  46. //返回值:无
  47. void MY_NVIC_SetVectorTable ( u32 NVIC_VectTab, u32 Offset )
  48. {
  49. //检查参数合法性
  50. assert_param ( IS_NVIC_VECTTAB ( NVIC_VectTab ) );
  51. assert_param ( IS_NVIC_OFFSET ( Offset ) );
  52. SCB->VTOR = NVIC_VectTab | ( Offset & ( u32 ) 0x1FFFFF80 ); //设置NVIC的向量表偏移寄存器
  53. //用于标识向量表是在CODE区还是在RAM区
  54. }
  55. //函数说明:设置NVIC分组
  56. //参数:NVIC_Group - NVIC分组 0~4 总共5组
  57. //返回值:无
  58. void MY_NVIC_PriorityGroupConfig ( u8 NVIC_Group )
  59. {
  60. u32 temp, temp1;
  61. temp1 = ( ~NVIC_Group ) & 0x07; //取后三位
  62. temp1 <<= 8;
  63. temp = SCB->AIRCR; //读取先前的设置
  64. temp &= 0X0000F8FF; //清空先前分组
  65. temp |= 0X05FA0000; //写入钥匙
  66. temp |= temp1;
  67. SCB->AIRCR = temp; //设置分组
  68. }
  69. //函数说明:设置NVIC
  70. //参数:NVIC_PreemptionPriority - 抢占优先级
  71. // NVIC_SubPriority - 响应优先级
  72. // NVIC_Channel - 中断编号
  73. // NVIC_Group - 中断分组 0~4
  74. // 注意优先级不能超过设定的组的范围!否则会死机
  75. // 组划分:
  76. // 组0:0位抢占优先级,4位响应优先级
  77. // 组1:1位抢占优先级,3位响应优先级
  78. // 组2:2位抢占优先级,2位响应优先级
  79. // 组3:3位抢占优先级,1位响应优先级
  80. // 组4:4位抢占优先级,0位响应优先级
  81. // NVIC_SubPriority和NVIC_PreemptionPriority的原则是,数值越小,越优先
  82. //返回值:无
  83. void MY_NVIC_Init ( u8 NVIC_PreemptionPriority, u8 NVIC_SubPriority, u8 NVIC_Channel, u8 NVIC_Group )
  84. {
  85. u32 temp;
  86. u8 IPRADDR = NVIC_Channel / 4; //每组只能存4个,得到组地址
  87. u8 IPROFFSET = NVIC_Channel % 4; //在组内的偏移
  88. IPROFFSET = IPROFFSET * 8 + 4; //得到偏移的确切位置
  89. MY_NVIC_PriorityGroupConfig ( NVIC_Group ); //设置分组
  90. temp = NVIC_PreemptionPriority << ( 4 - NVIC_Group );
  91. temp |= NVIC_SubPriority & ( 0x0f >> NVIC_Group );
  92. temp &= 0xf; //取低四位
  93. if ( NVIC_Channel < 32 ) NVIC->ISER[0] |= 1 << NVIC_Channel; //使能中断位(要清除的话,相反操作就OK)
  94. else NVIC->ISER[1] |= 1 << ( NVIC_Channel - 32 );
  95. NVIC->IPR[IPRADDR] |= temp << IPROFFSET; //设置响应优先级和抢断优先级
  96. }
  97. //函数说明:外部中断配置函数
  98. // 只针对GPIOA~G;不包括PVD,RTC和USB唤醒这三个
  99. //参数:GPIOx:0~6,代表GPIOA~G;
  100. // BITx:需要使能的位;
  101. // TRIM:触发模式,1,下降沿;2,上升沿;3,任意电平触发
  102. // 该函数一次只能配置1个IO口,多个IO口,需多次调用
  103. // 该函数会自动开启对应中断,以及屏蔽线
  104. //返回值:无
  105. void Ex_NVIC_Config ( u8 GPIOx, u8 BITx, u8 TRIM )
  106. {
  107. u8 EXTADDR;
  108. u8 EXTOFFSET;
  109. EXTADDR = BITx / 4; //得到中断寄存器组的编号
  110. EXTOFFSET = ( BITx % 4 ) * 4;
  111. RCC->APB2ENR |= 0x01; //使能io复用时钟
  112. AFIO->EXTICR[EXTADDR] &= ~ ( 0x000F << EXTOFFSET ); //清除原来设置!!!
  113. AFIO->EXTICR[EXTADDR] |= GPIOx << EXTOFFSET; //EXTI.BITx映射到GPIOx.BITx
  114. //自动设置
  115. EXTI->IMR |= 1 << BITx; // 开启line BITx上的中断
  116. //EXTI->EMR|=1<<BITx;//不屏蔽line BITx上的事件 (如果不屏蔽这句,在硬件上是可以的,但是在软件仿真的时候无法进入中断!)
  117. if ( TRIM & 0x01 ) EXTI->FTSR |= 1 << BITx; //line BITx上事件下降沿触发
  118. if ( TRIM & 0x02 ) EXTI->RTSR |= 1 << BITx; //line BITx上事件上升降沿触发
  119. }
  120. //函数说明:开机所有时钟寄存器复位
  121. //参数:无
  122. //返回值:无
  123. void MYRCC_DeInit ( void )
  124. {
  125. RCC->APB1RSTR = 0x00000000;//复位结束
  126. RCC->APB2RSTR = 0x00000000;
  127. RCC->AHBENR = 0x00000014; //睡眠模式闪存和SRAM时钟使能.其他关闭.
  128. RCC->APB2ENR = 0x00000000; //外设时钟关闭.
  129. RCC->APB1ENR = 0x00000000;
  130. RCC->CR |= 0x00000001; //使能内部高速时钟HSION
  131. RCC->CFGR &= 0xF8FF0000; //复位SW[1:0],HPRE[3:0],PPRE1[2:0],PPRE2[2:0],ADCPRE[1:0],MCO[2:0]
  132. RCC->CR &= 0xFEF6FFFF; //复位HSEON,CSSON,PLLON
  133. RCC->CR &= 0xFFFBFFFF; //复位HSEBYP
  134. RCC->CFGR &= 0xFF80FFFF; //复位PLLSRC, PLLXTPRE, PLLMUL[3:0] and USBPRE
  135. RCC->CIR = 0x00000000; //关闭所有中断
  136. //配置向量表
  137. #ifdef VECT_TAB_RAM
  138. MY_NVIC_SetVectorTable ( NVIC_VectTab_RAM, 0x0 );
  139. #else
  140. MY_NVIC_SetVectorTable ( NVIC_VectTab_FLASH, 0x0 );
  141. #endif
  142. }
  143. //函数说明:THUMB指令不支持汇编内联,实现执行汇编指令WFI
  144. //参数:无
  145. //返回值:无
  146. #ifndef CHANGE_IAR_SYS_C
  147. __asm void WFI_SET ( void )
  148. {
  149. WFI;
  150. }
  151. #else
  152. void WFI_SET ( void )
  153. {
  154. asm ( "WFI" );
  155. }
  156. #endif
  157. //函数说明:进入待机模式
  158. //参数:无
  159. //返回值:无
  160. void Sys_Standby ( void )
  161. {
  162. SCB->SCR |= 1 << 2; //使能SLEEPDEEP位 (SYS->CTRL)
  163. RCC->APB1ENR |= 1 << 28; //使能电源时钟
  164. PWR->CSR |= 1 << 8; //设置WKUP用于唤醒
  165. PWR->CR |= 1 << 2; //清除Wake-up 标志
  166. PWR->CR |= 1 << 1; //PDDS置位
  167. WFI_SET(); //执行WFI指令
  168. }
  169. //后备寄存器写入操作
  170. //reg:寄存器编号
  171. //reg:要写入的数值
  172. ////check ok
  173. ////091202
  174. //void BKP_Write(u8 reg,u16 dat)
  175. //{
  176. // RCC->APB1ENR|=1<<28; //使能电源时钟
  177. // RCC->APB1ENR|=1<<27; //使能备份时钟
  178. // PWR->CR|=1<<8; //取消备份区写保护
  179. // switch(reg)
  180. // {
  181. // case 1:
  182. // BKP->DR1=dat;
  183. // break;
  184. // case 2:
  185. // BKP->DR2=dat;
  186. // break;
  187. // case 3:
  188. // BKP->DR3=dat;
  189. // break;
  190. // case 4:
  191. // BKP->DR4=dat;
  192. // break;
  193. // case 5:
  194. // BKP->DR5=dat;
  195. // break;
  196. // case 6:
  197. // BKP->DR6=dat;
  198. // break;
  199. // case 7:
  200. // BKP->DR7=dat;
  201. // break;
  202. // case 8:
  203. // BKP->DR8=dat;
  204. // break;
  205. // case 9:
  206. // BKP->DR9=dat;
  207. // break;
  208. // case 10:
  209. // BKP->DR10=dat;
  210. // break;
  211. // }
  212. //}
  213. //函数说明:系统软复位
  214. //参数:无
  215. //返回值:无
  216. void Sys_Soft_Reset ( void )
  217. {
  218. SCB->AIRCR = 0X05FA0000 | ( u32 ) 0x04;
  219. }
  220. //函数说明:JTAG模式设置,用于设置JTAG的模式
  221. //参数:mode - jtag,swd模式设置;00,全使能;01,使能SWD;10,全关闭;
  222. //返回值:无
  223. void JTAG_Set ( u8 mode )
  224. {
  225. u32 temp;
  226. temp = mode;
  227. temp <<= 25;
  228. RCC->APB2ENR |= 1 << 0; //开启辅助时钟
  229. AFIO->MAPR &= 0XF8FFFFFF; //清除MAPR的[26:24]
  230. AFIO->MAPR |= temp; //设置jtag模式
  231. }
  232. //函数说明:系统时钟初始化函数
  233. //参数: pll - 选择的倍频数,从2开始,最大值为16
  234. //返回值:无
  235. void Stm32_Clock_Init ( u8 PLL )
  236. {
  237. unsigned char temp = 0;
  238. MYRCC_DeInit(); //复位并配置向量表
  239. RCC->CR |= 0x00010000; //外部高速时钟使能HSEON。 默认使用内部晶振,关闭外部晶振。
  240. while ( ! ( RCC->CR >> 17 ) ); //等待外部时钟就绪
  241. RCC->CFGR = 0X00000400; //APB1=DIV2;APB2=DIV1;AHB=DIV1;
  242. PLL -= 2; //抵消2个单位
  243. RCC->CFGR |= PLL << 18; //设置PLL值 2~16
  244. RCC->CFGR |= 1 << 16; //PLLSRC ON
  245. FLASH->ACR |= 0x32; //FLASH 2个延时周期
  246. RCC->CR |= 0x01000000; //PLLON
  247. while ( ! ( RCC->CR >> 25 ) ); //等待PLL锁定
  248. RCC->CFGR |= 0x00000002; //PLL作为系统时钟
  249. while ( temp != 0x02 ) //等待PLL作为系统时钟设置成功
  250. {
  251. temp = RCC->CFGR >> 2;
  252. temp &= 0x03;
  253. }
  254. }